简单实现js关键字new

782 阅读2分钟

构造函数调用

在JavaScript,构造函数只是一些 使用new 操作符时被调用的函数。它们并不会属于某个类,也不会实例化一个类。实际上, 它们甚至都不能说是一种特殊的函数类型,它们只是被new 操作符调用的普通函数而已。实际上并不存在“构造函数”这种特殊的函数,只有对于函数的“构造调用”。 我们来看一下函数的构造调用例子。

function foo(name, hobby) {
    this.name = name;
    this.hobby = hobby;
    //return 1; //如果返回了一个基本数据类型数据,下方的f并不会是1,而是一个对象
    //return {}; //如果返回了一个非基本数据类型数据,下方的f为此对象
}
foo.prototype.getName = function () {
    return this.name;
};
let f = new foo('vian', 'Game of Thrones');
console.log(f); //{name: 'vian', hobby: 'Game of Thrones'}
console.log(f.getName()); //vian
console.log(f.__proto__ === foo.prototype); //true

在JavaScript中使用new关键字对函数进行构造调用,这种使用方式跟其他面向对象的语言很像,但是实际上JavaScript中new的机制跟它们完全不同。

new机制

在使用关键字new调用一个函数(可以理解成构造调用)时,会自动执行下面的操作:

  • 创建一个全新的对象
  • 这个对象会被执行[[原型链接]]
  • 这个对象绑定到函数调用的this
  • 如果函数没有返回非基本数据类型数据,则返回这个对象

因此,JavaScript中并没有所谓的真正的构造函数,函数调用的区别就因为这个new机制。知道了这个new调用发生的事情后,自己实现一个new函数也变得很简单了。

实现一个new

function foo(name, hobby) {
    this.name = name;
    this.hobby = hobby;
}
foo.prototype.getName = function () {
    return this.name;
};
function newFunc(fn, ...args) {
    let defaultObj = Object.create(fn.prototype);
    let ret = fn.apply(defaultObj, args);
    return ret instanceof Object ? ret : defaultObj;
}
let f = newFunc(foo, 'vian', 'Game of Thrones');
console.log(f); //{name: 'vian', hobby: 'Game of Thrones'}
console.log(f.getName()); //vian
console.log(f.__proto__ === foo.prototype); //true

我们结合上面的new机制来解释一下这几句代码:

let defaultObj = Object.create(fn.prototype);

创建一个原型链接到函数原型对象的全新对象。

let ret = fn.apply(defaultObj, args);

这个对象绑定到函数调用的this。

return ret instanceof Object ? ret : defaultObj;

如果函数没有返回非基本数据类型,则返回这个对象。

希望本文对大家有所帮助,互相学习,一起提高,有说的不对的地方,师请纠正。转载请注明原帖。