对象是 new 进去的,那到底产生了什么?

什么,看到这个题目,大吃一惊,程序员居然有对象?当然有啦,这都什么年代了。不信,你来看看有了对象之后,面试官就会问你到底产生了什么?

业余一点讲述:

new 是用来实例化一个类的,而后在内存中调配一个实例对象。

咱们先来看看一个例子:

function Person(name) {    this.name = name;}Person.hairColor = "black";Person.prototype.say = function() {    console.log("My name is " + this.name);};var ken = new Person("人生代码");console.log(    ken.name, // "人生代码",      ken.hairColor, // undefined      ken.height // undefined);ken.say(); // "My name is 人生代码"console.log(    Person.name, // "Person"      Person.hairColor // "black");Person.say(); // Person.say is not a function

这段代码产生了什么?接下来就来揭晓答案

重点解析

第8行代码是要害:

var ken = new Person("人生代码");

Person 原本就是个一般的函数,只不过如果给他加了 new 操作,就变成了构造函数。

那么 JS 引擎在解析代码的时候,外部会做很多解决,伪代码如下:

new Person('人生代码') = {  var obj = {}; // 定义对象  var proto = Object.create(Person.prototype); // 复制原型  obj.__proto__ = proto; // 建设原型链  // obj->Person.prototype->Object.protorype->null  var res = Person.call(obj, '人生代码'); // 相当于 obj.Person('人生代码')  // 如果无返回值或者返回一个非对象值,则将obj返回作为新对象:    return typeof res === 'object' ? result || obj : obj;}

咱们能够得出以下几点:

  • obj.name 是在 Person.call(obj, '人生代码') 之后才赋值的
  • 等到 obj 经返回被赋给 ken 之后,ken.name 就是 '人生代码' 了

所以咱们能够画出以下原型链:

  • ken.name: 长期变量 objnameobj 经返回被赋给 kenken 的一些属性由此而来。
  • ken.hairColorken 实例对象 先查找本身的 hairColor,没有找到便会沿着原型链查找,在上述例子中,咱们仅在 Person 对象上定义了 hairColor,并没有在其原型链上定义,因而找不到。
  • ken.heightken 实例对象 先查找本身的 height,没有找到便会沿着原型链查找,原型链上也没有,因而找不到。
  • ken.sayken 会先查找本身的 say 办法,没有找到便会沿着原型链查找,在上述例子中,咱们在 Person.prototype 上定义了 say,因而在原型链上找到了say 办法。
  • 另外,在 say 办法中还拜访 this.name,这里的 this 指的是其调用者。如果 ken 调用 sayken 就是调用者,因而输入ken.name的值。

总结

new 运算符创立一个用户定义的对象类型的实例或具备构造函数的内置对象的实例。new 关键字会进行如下的操:

  • 创立一个空的简略JavaScript对象(即{});
  • 链接该对象(即设置该对象的构造函数)到另一个对象 ;
  • 将步骤1新创建的对象作为this的上下文 ;
  • 如果该函数没有返回对象,则返回this

代码实现请参考以下链接:

https://github.com/sisterAn/JavaScript-Algorithms/issues/71