# new关键字实现

我们都知道js通过new这个关键字可以为构造函创建实例对象,那这其中内部实现机制都有哪些呢?

# 举个例子

- 在es6还没有class这个语法糖的时候,我们创建一个构造函数都是下面这个样子
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    
    Person.prototype.sayName = function () {
        alert('hello, my name is' + this.name)
    }
    
 - 当我们去创建一个Person构造的实例时可以像下面这样
    const p = new Person('小明', 18);
    const p2 = new Person('小红', 17);
    
    p.name // 小明
    p2.name // 小红
    
    p.sayName(); //hello, my name is 小明
    p2.sayName(); //hello, my name is 小红
    
    从这个例子中,我们可以看到,实例 p、p2 可以:
    1.  访问到 Person 构造函数里的属性
    2.  访问到 Person.prototype 中的属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • 为了进一步探索这中间到底发生了什么,我们把代码直接拷贝到浏览器看下效果 image.png
  1. 实例p上[[prototype]] (也叫__proto__隐示原型)和 构造函数的prototype相同;也就是说实例对象可以调用构造函数的原型方法
  2. 另外发现p.__proto__.constructor === Person // true
  3. 那么是不是得到p.__proto__ === Person.prototype //true

# 实现方法

  • 按照上面这个思路上代码

function CreateNewConstructor() {
    
    //创建一个控对象
    var obj = new Object(),
    
    //截取构造函数

    Constructor = [].shift.call(arguments);
    
    //将实例的隐示原型指向构造函数的原型对象

    obj.__proto__ = Constructor.prototype;
    
    //构造函数执行并改变this指向obj

    Constructor.apply(obj, arguments);
    
    //返回实例对象

    return obj;

};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

验证

const p3 = CreateNewConstructor(Person, '小刚', 19);
p3.name // 小刚
p3.sayName(); //hello, my name is 小刚
1
2
3

# 原生new带返回值

1. 改造返回值对象
function Person(name, age, hobby) {
    this.name = name;
    this.age = age;
    return {
        hobby
    }
 }
 
 const p4 = new Person('小李', 20, 'football');
 p4.name // undefined
 p4.age // undefined;
 
 p4.hobby // football
 
 
2. 返回值是常规数据类型
function Person(name, age, hobby) {
    this.name = name;
    this.age = age;
    return 'hello,js'
 }
 
 const p5 = new Person('小王', 21, 'basketball');
 p5.name // 小王
 p5.age // 21;
 p5.hobby //undefined
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

结论总结

  1. 构造函数返回了一个对象,在实例中只能访问返回的对象中的属性。
  2. 如果没有返回值或者返回值是基本数据类型那么直接返回这个实例对象就好了

# 最终优化版本

    function CreateNewConstructor() {

        //创建一个控对象
        var obj = new Object(),

        //截取构造函数

        Constructor = [].shift.call(arguments);

        //将实例的隐示原型指向构造函数的原型对象

        obj.__proto__ = Constructor.prototype;

        //构造函数执行并改变this指向obj,并且用一个变量接收这个返回值结果

        const res = Constructor.apply(obj, arguments);

        //最终处理返回值
       
        return typeof res === 'object' ? res : obj;

    };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

TIP

最后欢迎大家留言交流

最后更新时间: 5/15/2023, 6:25:18 PM