js 面向对象 继承机制
根据w3cschool上的描述:共有3种继承方法(对象冒充,原型链,混合)
1、对象冒充:构造函数ClassA使用this关键字给所有属性和方法赋值,使ClassA构造函数成为ClassB的方法,调用。可实现多重继承。
注意:所有新属性和新方法都必须在删除新方法的代码行后定义,否则会覆盖父类的相关属性和方法,多重继承时存在同名问题。
原始:
function ClassA(sColor){
this.color = sColor
this.sayColor = function(){
alert(this.color);
};
};
function ClassB(sColor, sName){
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
//新属性和方法
this.name = sName;
this.sayName = function(){
alert(this.name);
}
}
var objA = new ClassA('blue');
var objB = new ClassB('red', 'jack');
call():function对象的一个方法,它是ECMASript把对象冒充规范化的结果
function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.call(this, sColor);
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
apple():与call类似,第二个参数是数组或arguments(参数对象,两个类中的参数顺序完全一致的话,才可以)
function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.apply(this, new Array(sColor));
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
以上存在内存浪费的问题。那就是对于每个实例对象而言,属性和方法都是一样的,但是每次创建新的实例,都要为其分配新的内存空间,这样做就会降低性能,浪费空间,缺乏效率。
2、原型链:把ClassB的prototype属性设置成ClassA的实例。ClassA的构造函数不能传递参数。
注意:所有新属性和新方法都必须在删除新方法的代码行后定义,否则会覆盖父类的相关属性和方法:因为prototype属性被替换成了新对象,添加了新方法和属性的原始对象将被销毁。
对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。对象冒充时不能这样(instanceof是讲类型的,而对象冒充是讲方法的。)。不支持多重继承。
//确保构造函数没有任何参数
function ClassA(){ }
//方法用原型链
ClassA.prototype.color = 'blue';
ClassA.prototype.sayColor = function(){
alert(this.color);
} function ClassB(){ }
//把 ClassB 的 prototype 属性设置成 ClassA 的实例
ClassB.prototype = new ClassA(); //新方法和属性
ClassB.prototype.name = '';
ClassB.prototype.sayName = function(){
alert(this.name);
}
3、混合方式:对象冒充的缺点,每个子类都有与父类相同的方法,这样很占空间;而原型链,子类只是指向父类的方法。但是不能多重继承。所以需要结合起来:对象冒充继承属性;原型链继承方法。
通过对象冒充方式继承时,所有的成员方法都是指向this的,也就是说new之后,每个实例将都会拥有这个成员方法,并不是共用的,这就造成了大量的内存浪费。并且通过对象冒充的方式,无法继承通过prototype方式定义的变量和方法(与我想的一样)
//父类属性用构造函数
function ClassA(sColor) {
this.color = sColor;
}
//不变的用原型链
ClassA.prototype.sayColor = function () {
alert(this.color);
};
//子类构造函数用对象冒充继承
function ClassB(sColor, sName) {
ClassA.call(this, sColor);
this.name = sName;
}
//方法用原型链继承
ClassB.prototype = new ClassA();
//
ClassB.prototype.constructor = ClassB
//新方法写在最后
ClassB.prototype.sayName = function () {
alert(this.name);
};
注意:所谓的新属性,在对象冒充中是this.name。在原型链中是prototype.name。
instanceof深入学习
(1)值类型:数值、布尔值、null、undefined。
(2)引用类型:对象、数组、函数。
instanceof为了弥补typeof的不足,作用:实例是否属于某种类型;实例是否属于它的父类型;
新概念:显示原型,隐式原型:新概念,哈哈
真难:http://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/
http://www.alloyteam.com/2015/06/javascript-shu-ju-jie-gou-he-suan-fa-jian-shu-qian-yan/
继承有三种方式:
1、
之前提到的混合方式
2、YUI继承
function Animal() {}
Animal.prototype.feeling = 'happy';
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
extend(Dog, Animal);
var dog = new Dog('二狗', '哈士奇');
print(dog.feeling); // happy
3、jquery继承
function Animal() {}
Animal.prototype.feeling = 'happy';
function deepCopy(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
}
deepCopy(Dog, Animal);
var dog = new Dog('二狗', '哈士奇');
print(dog.feeling); // happy
看情况用吧。
明白了
混合继承时,为什么要加:ClassB.prototype.constructor = ClassB
这篇教程写的很好,自己现在记录一下:http://www.jb51.net/article/22334.htm
重新覆盖prototype后,这条链上的对象和方法的constructor都变为object,为了纠正,需要把constructor重新定义。
对象继承 一般用混合方式比较好,w3cschool上的例子很清楚。
YUI的更高效和简洁。
js 面向对象 继承机制的更多相关文章
- js面向对象继承
前言 最近看到js面向对象这章节了,主要学习了原型和面向对象继承关系,为了梳理自己的知识逻辑,特此记录. js的面向对象 先说说我目前了解的js创建对象方法 1.写一个函数,然后通过new创建对象 2 ...
- 27、理解js的继承机制(转载自阮一峰)
Javascript继承机制的设计思想 作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...
- js面向对象 继承
1.类的声明 2.生成实例 3.如何实现继承 4.继承的几种方式 1.类的声明有哪些方式 <script type="text/javascript"> //类的声明 ...
- 关于JS面向对象继承问题
1.原型继承(是JS中很常用的一种继承方式) 子类children想要继承父类father中的所有的属性和方法(私有+公有),只需要让children.prototype=new father;即可. ...
- js 面向对象 继承
继承方式有四种: 1.call 2.apply 3.prototype 4.for in call 和 apply 的主要区别: call 传参数只能一个一个的传, apply 因为是用数组,所以可以 ...
- JS 面向对象 ~ 继承的7种方式
前言: 继承 是 OO 语言中的一个最为人津津乐道的概念.许多 OO 语言都支持两种继承方式:接口继承 和 实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.如前所述,由于函数没有签名,在 ...
- Javascript继承机制总结 [转]
转自:http://bbs.csdn.net/topics/260051906 Javascript继承 一直想对Javascript再次做一些总结,正好最近自己写了一个小型Js UI库,总结了一下J ...
- js面向对象之继承那点事儿根本就不是事
继承 说道这个继承,了解object-oriented的朋友都知道,大多oo语言都有两种,一种是接口继承(只继承方法签名):一种是实现继承(继承实际的方法) 奈何js中没有签名,因而只有实现继承,而且 ...
- js面向对象设计之class继承
EcmaScript 2015 (又称ES6)通过一些新的关键字,使类成为了JS中一个新的一等公民.但是目前为止,这些关于类的新关键字仅仅是建立在旧的原型系统上的语法糖,所以它们并没有带来任何的新特性 ...
随机推荐
- 简单AOP
代码如下 //使用说明 //1,新加接口与类 //2,新加类并实现ICallHandler类: ExecuteHandler //3,新建特性并实现HandlerAttribute和重写其中的Crea ...
- HTML 鼠标悬浮隐藏部分 习题
css样式表: @charset "utf-8"; /* CSS Document */ .a { width:80px; height:40px; background-colo ...
- ubuntu修改运行级别方法
Ubuntu系统设置启动级别的问题,因自己以前遇到过,故做过笔记记录了下来:Ubuntu.Debian系列与RedHat.CentOS启动级别含义有所区别:Ubuntu系列运行级别定义如下:0 – H ...
- Android中注解的使用
如果你是一名安卓开发者,你也一定听过大名鼎鼎的网络请求框架Retrofit.它将网络请求的方式以注解的形式展现,极大的提高了代码的可读性,同时网络请求集中写在一个interface中提高了代码的可维护 ...
- Python bytearray() 函数
Python bytearray() 函数 Python 内置函数 描述 bytearray() 方法返回一个新字节数组.这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < ...
- 快速排序C++实现
#include<iostream> using namespace std;class quicksort{ public: int quicks(int *a,int low,int ...
- oracle 使用正则表达式获取字符串中包含的数字
select REGEXP_REPLACE('字符串中包含的数字123,提取后就是123', '[^0-9]', '') from dual;
- AndroidStudio 导包遇到so文件的解决方案----------JPush推送
最近遇到 Couldn't load jpush175 from loader dalvik.system.PathClassLoader 这样一个问题 它说的是AS不能找到库文件 发生在于像Ecli ...
- js string 字符串
mutil lines string 多行字符串, 由于多行字符串用\n写起来比较费事,所以最新的ES6标准新增了一种多行字符串的表示方法,用...表示,是单撇号, 不是单引号. 这是一个 多行 字符 ...
- Linux 模块管理
查看模块信息 modinfo module-name 加载模块 insmod module-name 卸载模块 rmmod module-name 生成模块依赖 cd /lib/module/`una ...