Javascript 面向对象编程中的‘new’

0 一般函数调用

function personFn(name, age) {
    var personObj = {};

    personObj.name = name;
    personObj.age = age;
    
    return personObj;
}

var alex = personFn('Alex', 30);
console.log(alex); // -> { name: 'Alex', age: 30 }

1 使用new 创建对象

function PersonConstructor(name, age) {
    this.name = name;
    this.age = age;
}

var alex = new PersonConstructor('Alex', 30);
console.log(alex); // -> PersonConstructor { name: 'Alex', age: 30 }

使用new触发的函数一般称为“构造函数”,大写字母开头,生成的对象包含“构造函数”名+返回的对象

其实使用new触发函数,Javascript engine会特殊处理,下面注释的伪码可以看成Javscript engine加入的特殊处理

function PersonConstructor(name, age) {
    // this = {};
    // this.__proto__ = PersonConstructor.prototype;

    // Set up logic such that: if
    // there is a return statement
    // in the function body that
    // returns anything EXCEPT an
    // object, array, or function:
    //     return 'this' (the newly
    //     constructed object)
    //     instead of that item at
    //     the return statement;

    this.name = name;
    this.age = age;

    // return this;
}

整段代码可以分解为下面几个部分:

1 创建一个空对象,将它绑定给this

2 将对象的_proto_属性设置为构造函数的原型prototype

3 返回逻辑:如果代码没有返回,或者返回的不是object, array, 或者 function中的一种,那么将返回this

4 在代码末尾添加return, 如果代码中没有return

例子

function Demo() {
    console.log(this);
    this.value = 5;
    return 10;
}

/*1*/ var demo = new Demo(); // -> Demo {}
/*2*/ console.log(demo.__proto__ === Demo.prototype); // -> true
/*3*/ console.log(demo); // -> Demo { value: 5 }

function SecondDemo() {
    this.val = '2nd demo';
}

/*4*/ console.log(new SecondDemo()); // -> SecondDemo { val: '2nd demo' }

2 使用new 创建非构造函数

使用new 创建开头的普通函数,会发生什么?

function personFn(name, age) {
    var personObj = {};

    personObj.name = name;
    personObj.age = age;
    
    return personObj;
}

var alex = new personFn('Alex', 30);
console.log(alex); // -> { name: 'Alex', age: 30 }

结果和普通函数调用是一样的,我们看看Javascript engine 加入代码后的样子

function personFn(name, age) {
    // this = {};
    // this.constructor = PersonConstructor;
    // this.__proto__ = PersonConstructor.prototype;

    // Set up logic such that: if
    // there is a return statement
    // in the function body that
    // returns anything EXCEPT an
    // object, array, or function:
    //     return this (the newly
    //     constructed object)
    //     instead of that item at
    //     the return statement;

    var personObj = {};

    personObj.name = name;
    personObj.age = age;
    
    return personObj;
    
    // return this;
}

注释掉的代码主要做了下面四件事:

1 生成空对象,this绑定到这个空对象上

2 设置对象的构造函数和_proto_属性

3 设置返回逻辑

4 如果没有返回的话,添加return在代码的最后

其实这些操作并没有影响之前的代码,因为之前的代码并没有用到this, 而且也有返回对象

小结:使用new 对象时,构造函数里必须使用this才有价值

参考资料:

https://www.educative.io/collection/page/5679346740101120/5707702298738688/5750085036015616

猜你喜欢

转载自my.oschina.net/u/2510955/blog/1581436