• JavaScript 继承


    一、内部属性 [[prototype]]

    JavaScript 没有类的概念,它的“继承”基于对象的内部属性 [[prototype]],它是一个内部引用,它的值是引用类型值。

    ES6 中 class 语法是一种误导,它只是封装在 [[prototype]] 上的一个语法糖,它的行为像类,但又不同。

    JavaScript 中的原型链就是靠内部属性 [[prototype]] 关联起来的。关联的逻辑如下:

    1. 当访问一个对象的属性时,如果当前对象中不存在,就会在当前对象的内部属性 [[prototype]] 所指向的对象上进行查找,假设是 obj.__proto__
    2. 查找到,但立即返回该属性值。
    3. 没有查找到,就在当前对象的内部属性 [[prototype]] 所指向的对象上进行查找,就是 obj.__proto__.__proto__,以此类推。查找的终点对象就是 Object.prototype

    我们把这个查找过程,叫“在原型链上逐级向上查找”。

    取得对象的内部属性 [[prototype]],可以使用对象的非标准属性 __proto__,ES5 提供了一个标准方法 Object.getPrototypeOf(),可以达到同样目的。

    二、以构造的形式调用函数

    JavaScript 中没有构造函数的概念,只有“以构造的形式调用的函数”。调用函数时,前面加 new 就说这个函数,是以构造的形式调用的函数。

    function Foo() {  }
    
    new Foo(); // 以构造的形式调用的函数
    

    当一个函数以构造的形式调用的时候,与普通的函数调用方式有以下的区别:

    1. 创建、返回一个新对象。
    2. 函数中的 this 引用指向这个新对象。
    3. 新对象的内部 [[prototype]] 链指向函数的原型对象((new Foo()).__proto__ === Foo.prototype 值为 true)。
    function Foo(info) {
        this.info = info;
    }
    
    var f1 = new Foo('info1');
    var f2 = new Foo('info2');
    
    f1 === f2 // false;
    
    f1.info // info1
    f2.info // info2
    
    f1.__proto__ === f2.__proto__ // true
    f1.__proto__ === Foo.prototype // true
    
    f1.__proto__.constructor === Foo // true
    

    {注意} 函数的原型对象有一个属性 constructor,指向函数本身,就是说 (new Foo()).__proto__.constructor === Foo 值为 true

    三、寄生组合式继承

    这是最常选择的继承方式。

    function inheritPrototype(subType, superType) {
        subType.prototype = Object.create(superType.prototype);
        subType.prototype.constructor = subType;
    }
    
    // Shape - superclass
    function Shape() {
      this.x = 0;
      this.y = 0;
    }
    
    // superclass method
    Shape.prototype.move = function(x, y) {
      this.x += x;
      this.y += y;
      console.info('Shape moved.');
    };
    
    // Rectangle - subclass
    function Rectangle() {
      Shape.call(this); // call super constructor.
    }
    
    // subclass extends superclass
    inheritPrototype(Rectangle, Shape);
    
    var rect = new Rectangle();
    
    console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
    console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
    rect.move(1, 1); // 打印 'Shape moved.'
    

    rect 对象有两个实例属性 xyrect.__proto__ 指向 Rectangle.prototyperect.__proto__.constructor 指向 Rectangle(手动赋予的);Rectangle.prototype.__proto__ 指向 Shape.prototypeShape.prototype.constructor 指向 Shape

    四、参考链接

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

    (完)

  • 相关阅读:
    【Office】将一个excel文件中的表移动至另一个excel中
    【 DB_Oracle】impdp/expdp导入导出dmp文件
    【DB_Oracle】设置Oracle的监听和服务随 Linux开机自启
    【DB_Oracle】Centos中安装oracle11g R2
    【 DB_Oracle】Linux下启动Oracle服务和监听程序
    【OS_Linux】VMware中给CentOS磁盘扩容
    【 OS_Linux】WinSCP实现Windows与Linux间文件的传输
    【DB_Oracle】windows下安装Oracle 11g
    鼠标键盘失灵对策(Windows8.1)
    UNIX 高手的另外 10 个习惯
  • 原文地址:https://www.cnblogs.com/zhangbao/p/6587773.html
Copyright © 2020-2023  润新知