zoukankan      html  css  js  c++  java
  • JavaScript中的constructor和继承

    概述

    这是我在看JavaScript面向对象编程指南的时候,对constructor和继承的总结。

    关于它们的详细知识,可以上网查到,所以我只写那些网上没有的。

    内容

    • constructor的理解
    • constructor的实际用途
    • constructor的陷阱
    • 从应用角度理解继承
    • 函数构造器的继承
    • 纯对象的继承

    constructor的理解

    constructor 属性是一个指针,指向创建此对象的函数。(可以更改)

    constructor的实际用途

    看下面这段代码:

    var a,b;
    (function(){
      function A (arg1,arg2) {
        this.a = 1;
        this.b=2; 
      }
    
      A.prototype.log = function () {
        console.log(this.a);
      }
      c = new A();
    })()
    c.log();
    // 1
    

    实例c是用闭包建立的,但是因为A是在闭包里面,所以我们不能直接访问A。但是如果需要给A添加方法怎么办呢?方法是用constructor

    c.constructor.prototype.log2 = function () {
      console.log(2)
    }
    
    c.log2();
    // 2
    

    constructor的陷阱

    //继承
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    

    我们一般在继承中,要给constructor属性进行重置,比如上面那段代码,这是为什么呢?

    先来看看一个例子:

    function Dog(){this.tail = true;}
    var benji = new Dog();
    Dog.prototype.say = function(){return 'woof';};
    
    Dog.prototype = {paws:4}
    var lucy = new Dog();
    
    benji.constructor.prototype.paws
    //4
    lucy.constructor.prototype.paws
    //undefined
    
    

    其中,benjilucy都是Dog()的子对象,但是结果却不相同。造成这种结果的原因是Dog.prototype = {paws:4}重置了Dog()的原型。(原理不明,貌似和__proto__有关。)

    如果在Dog.prototype = {paws:4}后面再加一条语句Dog.prototype.constructor = Dog;结果就一样了。这也是为什么在继承中要重置constructor的原因。

    从应用角度理解继承

    继承,就是对父元素的代码复用。

    //父元素是函数构造器
    function Parent() {
    	this.id = 3;   //带this的自身属性
    	var od = 5;  //不带this的自身属性
    }
    Parent.prototype.ud = 7;  //原型属性
    
    //父元素是纯对象
    Parent= {id:9};
    Parent.prototype.ud = 7;
    

    综合考虑一下,父元素分为2种:函数构造器和纯对象。父元素里面的代码又分为自身属性和原型属性。(方法和属性差不多,所以只考虑属性。)

    所以我们分别来讨论函数构造器和纯对象的代码复用,即属性继承。

    函数构造器的继承

    • 只继承原型属性

    很简单,只需要把父对象的原型赋值给子对象即可。(原型继承法

    Child.prototype = Parent.prototype;
    

    但是这样的话,修改子对象的原型会影响父对象的原型,所以我们考虑用闭包。(临时构造器法

    var F = function() {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    

    但是如果子对象的prototype本来就有值,所以不能直接进行prototype的赋值。这个时候我们可以直接把属性拷贝过去。(原型属性拷贝法

    var p = Parent.prototype;
    var c = Child.prototype;
    for (i in p) {
        c[i] = p[i];
    }
    

    当然,还有深拷贝法,这里就不贴代码了。

    • 只继承自身属性。

    首先想到的就是拷贝法,上面贴过代码这里就补贴了。但是拷贝法只能继承父对象中不带this的自身属性。

    如果想只继承带this的自身属性,可以用构造器借用法

    function Child() {
        Parent.apply(this, argument);
    }
    

    如果想全部继承的话,那就只能两者结合了。

    • 同时继承自身属性和原型属性

    这个时候,我们第一个想到的就是用new。(原型链法

    Child.prototype = new Parent();
    

    需要注意的是,这时子对象仅继承父对象中带有this的自身元素,不继承不带this的自身元素。

    其它方法就只能结合上面多个方法了。

    纯对象的继承

    • 只继承原型属性。

    和函数构造器的继承一样。

    • 只继承自身属性。

    当父元素是纯对象的时候,它里面没有this的自身元素。所以只需用拷贝法即可。

    另外,还可以把父元素的自身元素放到子元素的prototype里面去。(原型继承法)

    function object() {
        function F(){};
        F.prototype = Parent;
        return new F();
    }
    
    • 同时继承自身属性和原型属性

    这个就是结合上述方法了。

  • 相关阅读:
    candy——动态规划
    HTTP协议(转)
    linked-list-cycle-ii——链表,找出开始循环节点
    linked-list-cycle——链表、判断是否循环链表、快慢指针
    转: utf16编码格式(unicode与utf16联系)
    【转】Nginx模块开发入门
    【转】依赖注入那些事儿
    转: OpenResty最佳实践
    转:linux的源码查看, c++语法 查看网站
    【转】所需即所获:像 IDE 一样使用 vim
  • 原文地址:https://www.cnblogs.com/yangzhou33/p/8407406.html
Copyright © 2011-2022 走看看