第14题 - new操作符内部实现原理

2,940 阅读2分钟

面试题目:

new 操作符内部实现原理是什么?

答案解析:

new 操作符经常被用到,用面向对象语言们通用的观点来看:new 是用来实例化一个类,从而在内存中分配一个实例对象。

new 关键字会进行如下操作:

  1. 创建一个空的JavaScript对象(即{});
  2. 将函数的 prototype 赋值给对象的 __proto__属性 ;
  3. 调用函数,并将步骤1新创建的对象作为函数的this上下文 ;
  4. 如果该函数没有返回值或者返回值不是对象,则返回创建的对象,如果返回值是对象,则直接返回该对象。

示例:

function Person(name) {
    this.name = name;
}
function Person2(name) {
    this.name = name;
    return this.name;
}
function Person3(name) {
    this.name = name;
    return new Array();
}
function Person4(name) {
    this.name = name;
    return new String(name);
}
function Person5(name) {
    this.name = name;
    return function() {};
}


var person = new Person('John');  // {name: 'John'}
var person2 = new Person2('John');  // {name: 'John'}
var person3 = new Person3('John');  // []
var person4 = new Person4('John');  // 'John'
var person5 = new Person5('John');  // function() {}

Person本身是一个普通函数,当通过new来创建对象时,Person就是构造函数了。

JS引擎执行这句代码时,在内部做了很多工作,用伪代码模拟其工作流程如下:

new Person("John") = {
    var obj = {};
	obj.__proto__ = Person.prototype; // 此时便建立了obj对象的原型链: obj->Person.prototype->Object.prototype->null
	var result = Person.call(obj,"John"); // 相当于obj.Person("John")
	return typeof result === 'object' ? result : obj; // 如果无返回值或者返回一个非对象值,则将obj返回作为新对象
}

延伸

原型链是面试中必考题目,new 和原型链经常一起出现,看下面这道题目:

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

var child = new Parent('前端名狮');
console.log(Parent.prototype); // {constructor: function Parent(name){this.name = name}}
console.log(child.prototype); // undefined

JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object ,Function 是JS自带的函数对象。 函数对象会预定义一个属性就是原型对象prototype。注:普通对象没有prototype,但有__proto__属性。

Parent是函数对象,Parent.prototype是存在的。

由上面的new 操作符的工作原理,我们知道它返回的是一个普通对象{},所以它是没有prototype属性的,输出undefined


扫一扫 关注我的公众号【前端名狮】,更多精彩内容陪伴你!

【前端名狮】