JavaScript继承学习笔记

一、类式继承

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"  实例属性 

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

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"

4、共享原型:本模式不调用父类构造函数。基本思想是:可复用成员转义到原型中,而不是在this中。将子原型与父原型设置为相同。

缺点:(1)由于对象共享了原型,如果子对象修改了原型,则所有对象都将受到影响。

1 function inherit(Child, Parent) {
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 })();

二、原型式继承

 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"

三、复制属性实现继承

 (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" 父对象被修改

(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"

(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 }

四、借用方法:重用对象的某些方法,又不希望形成父子继承关系。通过使用call(),apply()函数方法来实现。

function f() {
    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"

 为原型添加绑定

 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 }

原文地址:https://www.cnblogs.com/wuzy/p/3010167.html