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

  • 相关阅读:
    linq 喜悦
    五班二组高级软件测试作业一总结
    五班二组高级软件测试进度报告
    五班二组黑盒测试实践作业进度报告(1)
    五班二组高级软件测试进度报告
    五班二组高级软件测试进度报告
    [ 语文 ] 西游记50~52回阅读笔记
    [ 具体数学 ] 0:前言
    [ 具体数学 ] 3:和式与封闭式
    [ 历史 ] 黄巢起义
  • 原文地址:https://www.cnblogs.com/wuzy/p/3010167.html
Copyright © 2020-2023  润新知