今天在重温ES6中的promise一章的时候,看到这样一段:
Promise 新建后就会立即执行。
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
上面代码中,Promise 新建后立即执行,所以首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。
上面说是Promise 新建后立即执行,所以首先输出的是Promise,那么为验证,我这样改了一下,如下:
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
console.log('Hi!');
// Promise
// Hi!
结果很明显,对于new构造函数之后具体执行了哪些,看来我要好好梳理一下了。
然后自己梳理和百度了一下:
new在执行构造函数时
①在内存中创建一个新对象
②让this指向这个新对象
③执行构造函数里的代码,给这个新对象添加属性和方法
④返回这个新对象(所以构造函数里面不需要return)
让我们用实例来说明一下
function base(){
console.log("base");
this.name = name;
}
var item = new base();
// base
上面的执行步骤如下:
1、先创建了一个空对象 obj
var obj = {}
2、设置obj的_proto_为原型
obj._proto_ = base.prototype;
3、使用obj作为上下文调用Base函数
var result = base.call(obj);
关于call和apply的原理,请看我这篇文章:js中的call()和apply()函数实现原理
4、如果构造函数返回的是原始值,那么这个返回值会被忽略,如果返回的是对象,就会覆盖构造的实例
if(typeof result == 'object'){
return result;
} else {
return obj;
}
结合上面四步来看,在第三步的时候执行了Base.call(obj),所以才会输出base这个值。
具体的代码实现逻辑如下:
function realizeNew(constr, ...args) {
if (typeof constr != 'function') {
throw new TypeError('not function')
}
let obj = Object.create(constr.prototype)
// 等同于下面的代码
// let obj = {}
// obj.__proto__ = constr.prototype
// let args = [...arguments].slice(1) // 如果在所在的函数中直接传args,就不用写这一行了。
let result = constr.call(obj, ...args);
if (typeof result == 'object') {
return result
} else {
return obj
}
}