XXHolic / segment

some notes
MIT License
28 stars 4 forks source link

The new Operator #39

Open XXHolic opened 5 years ago

XXHolic commented 5 years ago

目录

想法

在进行回顾的时候想到了这个,通过查询资料对比了一下,感觉有必要整理一下。

作用

new 操作符创建一个用户定义对象类型或具有构造函数的内置对象的实例。

在传统的面向类的语言中,“构造函数”是类中一些特殊方法,使用 new 初始化类时会调用类中的构造函数。JavaScript 中 new 的机制和面向类语言完全不同。JavaScript 中的“构造函数”跟一般函数的唯一区别就是调用的方式不同,实际上并不存在所谓的“构造函数”,只有对于函数的“构造调用”。

在使用 new 来调用函数时,会执行下面的操作:

  1. 创建一个新的对象。
  2. 这个新对象会执行 [[prototype]] 连接。
  3. 这个新对象会绑定到函数调用的 this
  4. 如果函数没有返回其它对象,那么会自动返回这个新对象。

prototype

JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,是对于其他对象的引用。当在对象中查找属性时,首先检查对象本身是否有这个属性,如果有的话就使用它。如果没有,就会继续访问对象的 [[Prototype]] 链。这个过程会持续到找到匹配的属性名或者查找完整条 [[Prototype]] 链。

所有普通的 [[Prototype]] 链最终都会指向内置的 Object.prototype。由于所有的“普通”(内置,不是特定主机的扩展)对象都“源于” Object.prototype 对象,它包含 JavaScript 中许多通用的功能,比如说 toString()valueOf()

示例

这里主要对 第 2 步进行解释。

    function Book(name) {
      this.name = name;
    }

    Book.prototype.printName = function() {
      console.log("Print book name:",this.name);
    };

    console.info(Book.prototype.constructor === Book); // true
    var newBook = new Book('How to read');
    console.info(newBook.constructor === Book);  // true

    console.info("book name:",newBook.name);
    newBook.printName();

Book.prototype 默认有一个公有并且不可枚举的属性 constructor ,这个属性引用的是对象关联的函数(这里是 Book)。可以看到通过 new Book() 创建的对象好像有个 constructor 属性,也是指向创建的函数。但不是这样。实际上,constructor 引用同样被委托给了 Book.prototype ,而 Book.prototype.constructor 默认是指向 Book,所以比较的值是 true 。可以把相应的值打印出来看看。

console.info("Book.prototype ",Book.prototype);
console.info('newBook ',newBook);
console.info('newBook.__proto__ ',newBook.__proto__);

37-console

可以发现对象 newBook 本身是没有 constructor 属性,而是在 new Book() 过程中将 newBook 内部 [[Prototype]] 关联到 Book.prototype 上。

再回过头来看,就可以发现并没有所谓的“构造函数”,constructor 在语义上很容易造成误解,需要记住的是“ constructor 并不表示被构造”。

参考资料