一、类式继承
1、默认模式:该模式子类继承了父类的实例属性,原型属性和方法。
缺点:(1)子类同时继承了父类和父类原型两个对象,而父类的自身属性往往是不需要的;
(2)子构造函数不支持参数传递
1 //父类
2 var Parent = function(name) {
3 this.name = name || "Adam";
4 }
5 Parent.prototype.getName = function() {
6 return this.name;
7 };
8 //子类
9 function Child() {};
10 Child.prototype = new Parent();//继承
11
12 var child = new Child();
13 child.getName();//"Adam" 原型方法
14 child.name;//"Adam" 实例属性
2 var Parent = function(name) {
3 this.name = name || "Adam";
4 }
5 Parent.prototype.getName = function() {
6 return this.name;
7 };
8 //子类
9 function Child() {};
10 Child.prototype = new Parent();//继承
11
12 var child = new Child();
13 child.getName();//"Adam" 原型方法
14 child.name;//"Adam" 实例属性
15 console.log(child.hasOwnProperty("name"));//false
2、借用构造函数:解决从子构造函数到父构造函数传递参数的问题。子类中保存着父类对象的真实副本,不会存在子类对象意外覆盖父类对象属性的风险。
缺点:(1)无法继承原型对象
1 //父类构造函数
2 function Parent(name) {
3 this.name = name;
4 }
5 var parent = new Parent();
6 function Child(name){
7 Parent.apply(this, arguments);
8 }
9 var child = new Child("JS");
10 console.log(child.hasOwnProperty("name"));//true
2 function Parent(name) {
3 this.name = name;
4 }
5 var parent = new Parent();
6 function Child(name){
7 Parent.apply(this, arguments);
8 }
9 var child = new Child("JS");
10 console.log(child.hasOwnProperty("name"));//true
3、借用与设置原型:结合默认继承与借用构造函数两种模式,即先借用构造函数,然后设置子构造函数的原型使其指向父类构造函数的实例。
缺点:(1)父类构造函数被调用两次,效率低下
1 //父类构造函数
2 function Parent(name) {
3 this.name = name || "Adam";
4 }
5 Parent.prototype.getName = function() {
6 return this.name;
7 }
8
9 //子构造函数
10 function Child(name) {
11 Parent.apply(this, arguments);
12 }
13 Child.prototype = new Parent();
14
15 var child = new Child("kid");
16 child.name;//"kid"
17 delete child.name;
18 child.name;//"Adam"
2 function Parent(name) {
3 this.name = name || "Adam";
4 }
5 Parent.prototype.getName = function() {
6 return this.name;
7 }
8
9 //子构造函数
10 function Child(name) {
11 Parent.apply(this, arguments);
12 }
13 Child.prototype = new Parent();
14
15 var child = new Child("kid");
16 child.name;//"kid"
17 delete child.name;
18 child.name;//"Adam"
4、共享原型:本模式不调用父类构造函数。基本思想是:可复用成员转义到原型中,而不是在this中。将子原型与父原型设置为相同。
缺点:(1)由于对象共享了原型,如果子对象修改了原型,则所有对象都将受到影响。
1 function inherit(Child, Parent) {
2 Child.prototype = Parent.prototype;
3 }
2 Child.prototype = Parent.prototype;
3 }
5、临时构造函数:断开父子类对象原型之间的直接链接关系,解决共享原型所带来的问题。
1 var inherit = (function (Child, Parent) {
2 function F() {};
3 return function(Child, Parent) {
4 F.prototype = Parent.prototype;//断开父子对象的直接链接
5 Child.prototype = new F();
6 Child.uber = Parent.prototype;//保存父对象原型
7 Child.prototype.constructor = Child;//对象类别
8 };
9 })();
2 function F() {};
3 return function(Child, Parent) {
4 F.prototype = Parent.prototype;//断开父子对象的直接链接
5 Child.prototype = new F();
6 Child.uber = Parent.prototype;//保存父对象原型
7 Child.prototype.constructor = Child;//对象类别
8 };
9 })();
二、原型式继承
1 //需要继承的对象
2 var Parent = function() {
3 this.name = "Adam";
4 };
5
6 Parent.prototype.getName = function() {
7 return this.name;
8 }
9 var parent = new Parent();
10 var child = object(parent);
11
12 function object(parent) {
13 function F() {};
14 F.prototype = parent;
15 return new F();
16 }
17
18 child.getName;//"Adam"
2 var Parent = function() {
3 this.name = "Adam";
4 };
5
6 Parent.prototype.getName = function() {
7 return this.name;
8 }
9 var parent = new Parent();
10 var child = object(parent);
11
12 function object(parent) {
13 function F() {};
14 F.prototype = parent;
15 return new F();
16 }
17
18 child.getName;//"Adam"
三、复制属性实现继承
(1)浅复制
//浅复制
function extend(parent, child) {
var i;
child = child || {};
for (i in parent) {
if (parent.hasOwnProperty(i)) {
child[i] = parent[i];
}
}
return child;
}
var parent = {name:"Adam", web:["js", "html"]};
var child = extend(parent);
child.name;//"Adam"
child.web.push("css");
parent.web;//"js", "html", "css" 父对象被修改
function extend(parent, child) {
var i;
child = child || {};
for (i in parent) {
if (parent.hasOwnProperty(i)) {
child[i] = parent[i];
}
}
return child;
}
var parent = {name:"Adam", web:["js", "html"]};
var child = extend(parent);
child.name;//"Adam"
child.web.push("css");
parent.web;//"js", "html", "css" 父对象被修改
(2)深度复制
//深度复制
function extendDeep(parent, child) {
var i;
child = child || {};
for (i in parent) {
if (parent.hasOwnProperty(i)) {
if (typeof parent[i] === "object" ) {
child[i] = Object.prototype.toString.call(parent[i]) === "[object Array]" ? [] : {};
extendDeep(parent[i], child[i]);
} else {
child[i] = parent[i];
}
}
}
return child;
}
var parent = {name:"Adam", web:["js", "html"]};
var child = extend(parent);
child.name;//"Adam"
child.web.push("css");
parent.web;//"js", "html"
function extendDeep(parent, child) {
var i;
child = child || {};
for (i in parent) {
if (parent.hasOwnProperty(i)) {
if (typeof parent[i] === "object" ) {
child[i] = Object.prototype.toString.call(parent[i]) === "[object Array]" ? [] : {};
extendDeep(parent[i], child[i]);
} else {
child[i] = parent[i];
}
}
}
return child;
}
var parent = {name:"Adam", web:["js", "html"]};
var child = extend(parent);
child.name;//"Adam"
child.web.push("css");
parent.web;//"js", "html"
(3)混入复制
1 //复制多个对象
2 function mix() {
3 var arg, prop, child = {};
4 for (arg = 0; arg < arguments.length; arg++) {
5 for (prop in arguments[arg]) {
6 if (arguments[arg].hasOwnProperty(prop)) {
7 child[prop] = arguments[arg][prop];
8 }
9 }
10 }
11 return child;
12 }
2 function mix() {
3 var arg, prop, child = {};
4 for (arg = 0; arg < arguments.length; arg++) {
5 for (prop in arguments[arg]) {
6 if (arguments[arg].hasOwnProperty(prop)) {
7 child[prop] = arguments[arg][prop];
8 }
9 }
10 }
11 return child;
12 }
四、借用方法:重用对象的某些方法,又不希望形成父子继承关系。通过使用call(),apply()函数方法来实现。
function f() {
var args = [].slice.call(arguments, 1, 3);
console.log(args);
}
f(1, 2, 3, 4, 5);//[2, 3]
var args = [].slice.call(arguments, 1, 3);
console.log(args);
}
f(1, 2, 3, 4, 5);//[2, 3]
对象绑定
1 var one = {
2 name: "object",
3 say: function (greet) {
4 console.log(greet + ", " + this.name);
5 }
6 };
7
8 var another = {
9 name: "another",
10
11 method: function(callback) {
12 callback("a");
13 }
14 }
15 one.say.call(another,"hi");//"hi, another"
16 another.method(one.say);//"a, undefined"
17
18 //对象绑定
19 function bind(o, m) {
20 return function() {
21 return m.apply(o,[].slice.call(arguments));
22 };
23 }
24 var say = bind(another, one.say);
25 say("a");// "a , another"
2 name: "object",
3 say: function (greet) {
4 console.log(greet + ", " + this.name);
5 }
6 };
7
8 var another = {
9 name: "another",
10
11 method: function(callback) {
12 callback("a");
13 }
14 }
15 one.say.call(another,"hi");//"hi, another"
16 another.method(one.say);//"a, undefined"
17
18 //对象绑定
19 function bind(o, m) {
20 return function() {
21 return m.apply(o,[].slice.call(arguments));
22 };
23 }
24 var say = bind(another, one.say);
25 say("a");// "a , another"
为原型添加绑定
1 if (typeof Function.prototype.bind === "undefined") {
2 Function.prototype.bind = function (obj) {
3 var fn = this,
4 slice = Array.prototype.slice,
5 args = slice.call(arguments, 1);
6
7 return function() {
8 return fn.apply(obj, args.concat(slice.call(arguments)));
9 };
10 };
11 }
2 Function.prototype.bind = function (obj) {
3 var fn = this,
4 slice = Array.prototype.slice,
5 args = slice.call(arguments, 1);
6
7 return function() {
8 return fn.apply(obj, args.concat(slice.call(arguments)));
9 };
10 };
11 }