JavaScript new原理

首先,来看一段代码,我们用两种方法来创建一个对象

function Person(age){
    this.age= age;
    console.log(this);
    return {age:age};//返回对象
}
var person1 = new Person(20);
var person2 = Person(18);
 
console.log(person1);
console.log(person2);
结果1

两种实例化对象方式,一个使用了new关键字,一个没有。
从图里可以看出 两者最大的区别在于执行时的执行上下文不同。一个在Person对象中执行,一个在window。前者是真正实例化了一个对象,后者并没有。

new操作符做了什么?

    1. 创建一个新对象
    1. 将函数的作用域赋给新对象(这里实际上就是生产了一个新的上下文)
    1. 执行函数中的代码(为新对象添加属性、方法)
    1. 考察第3步返回的返回值,无返回值或者返回一个非对象值时,则将创建的新对象返回,否则会将返回值作为新对象返回。(也就是说一定会返回一个对象回来,这一步可以从下面的代码得结论)
new Person(20) = { // new 实际执行情况

    var obj = {};

    obj.__proto__ = Person.prototype;

    var result = Person.call(obj,20);

    return typeof result === 'object'? result : obj;
}  // Person{age: 20}

所以,上面var person1 = new Person(20);执行时,先创建了一个新的对象obj{},再把这个对象的_proto_ 指向Person的原型对象prototype

(题外话:此时新对象的原型链为obj._proto_ >Person.prototype->Object.prototype->null,obj继承Person.prototype上的属性方法,实现了JavaScript的继承)

原型链

因此 this 就指向了这个新对象,再把age的属性赋予person1,最后返回了一个带有属于age为20的对象。而不使用new的,只是把函数的执行结果返回。

function Person(age){
    this.age= age;
    console.log(this);
    return age; // 如果去掉这里,console.log(person2);为undefined
}
var person1 = new Person(20);
var person2 = Person(18);
 
console.log(person1);
console.log(person2);
结果2

修改代码后,没有使用new进行实例化的仅仅是得到函数执行的结果,而使用了new进行实例化是得到一个新的对象。虽然这里函数返回是一个值而不是对象,但是基于new执行的第四步,返回值是非对象的值,依然会把内部新建的Person对象返回。

总结:
通过new操作符,我们可以创建原对象的一个实例对象,而这个实例对象继承了原对象的属性和方法,所以new存在的意义在于它实现了javascript中的继承,而不仅仅是实例化了一个对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容