js篇-new操作符

137 阅读2分钟

文章参考:juejin.cn/post/684490…

new做了什么

先看一个例子:

    function Test(name) {
      this.name = name
    }
    Test.prototype.sayName = function () {
        console.log(this.name)
    }
    const t = new Test('hello')
    console.log(t.name) // 'hello'
    t.sayName() // 'hello'
  • new通过构造函数test创建出来的实例t,可以访问到构造函数中的属性name
  • 创建出来的实例,可以访问到构造函数原型链中的属性sayName

关于原型链,我们再看个例子

    function Test(name) {
      this.name = name
    }
    Test.prototype.sayName = function () {
        console.log(this.name)
    }
    const t = new Test('hello')
    console.log(t)

    var obj = new Object();
    console.log(obj)

看下结果:

截屏2022-05-02下午12.46.18.png

新生成的对象下面有一层prototype,它的constructor是Test函数,test函数再套了一层prototype,constructorObject,这是js自带的。

所以这也印证了上面第二点,创建的实例对象拥有构造函数的prototype

可以看下这张图理解函数的原型关系

image.png

给构造函数添加一个返回值

function Test(name) {
  this.name = name;
  return 1;
}
Test.prototype.sayName = function () {
    console.log(this.name)
}
const t = new Test('hello')
console.log(t.name) // 'hello'
t.sayName() // 'hello'

在控制台执行上述代码,发现return并没起到任何作用

改成return { a: 1};

function Test(name) {
  this.name = name;
  return { a: 1};
}
Test.prototype.sayName = function () {
    console.log(this.name)
}
const t = new Test('hello')
console.log(t) // { a: 1}
t.sayName() // 报错

可以看到改成返回对象后,实例t变成了返回的对象

总结:构造函数尽量不要设置返回值,会导致new操作符失效

手写实现new操作符

从上面的例子可以看到new操作符具体做了这些事情

  • 返回一个对象(内部需要创建一个对象)
  • 函数的this绑定到生成的新对象上(需要修改this指向)
  • 创建的每个新对象最终都会被[[Prototype]]链接到这个函数的prototype对象上(需要将对象与构造函数的原型链接起来)
  • 函数没有返回对象类型,那调用new创建的实例,会返回这个新的对象

来看看怎么实现

function newFunc(Con, ...args) {
  let obj = {}; //1、创建一个空对象
  obj.__proto__ = Con.prototype; // 2、将构造函数的原型对象,作为新对象的原型对象
  let result = Con.apply(obj, args); // 3、让构造函数的this指向新对象obj
  return result instanceof Object ? result : obj;  // 4、判断构造函数返回的是否是一个对象,是的话,就返回构造函数返回的值,否则,返回obj
}

检验下:

function Test(name) {
  this.name = name;
}
Test.prototype.sayName = function () {
    console.log(this.name)
}
const t = newFunc(Test, 'hello');
console.log(t.name) // hello
t.sayName() // hello

通过手写,可以看到构造函数也是改变this指向的一种方式。