构造函数调用
在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;
如果函数没有返回非基本数据类型,则返回这个对象。
希望本文对大家有所帮助,互相学习,一起提高,有说的不对的地方,师请纠正。转载请注明原帖。