这是我参与更文挑战的第1天,活动详情查看:更文挑战
new
在js中我们都是通过, new 一个构造函数,获得实例的。然后这个实例就可以调用原型链上的方法。 new的实现其实很简单,简单的来说就做了4件事
- 创建一个新对象
- 将新对象的__proto__ 指向构造函数的原型链
- 调用构造函数同时,将this 指向当前的新对象。
- 判断构造函数的返回值, 决定 返回什么。
直接看下面代码。
function myNew(ctor,...args) {
if(typeof ctor !== 'function') {
throw new Error('type error')
}
let obj = new Object();
// 原式继承
obj.__proto__ = Object.create(ctor.prototype);
let res = ctor.aply(obj,args);
// 判断当前 构造函数 返回值是不是函数或者是 对象
const isObject = typeof res == "object" && typeof res !== "null";
const isFunction = type of res === 'function';
return isObject || isFunction ? res : obj
}
bind
bind 返回一个指定this的新函数。
bind 函数实现的难点主要在于当 bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效。
只要了解new 的实现原理, 才能对手写bind的才能理解。 其实就是我bind 一次this之后, 如果我将bind 返回的函数作为构造函数再去 new 的话。 因为new 也会改变 this, 所以这里做一个this 判断, 保证实例的属性不手影响。
总结:
在《JavaScript模式》这本书中,new的过程说的比较直白,当我们new一个构造器,主要有三步:
• 创建一个空对象,将它的引用赋给 this,继承函数的原型。
• 通过 this 将属性和方法添加至这个对象
• 最后返回 this 指向的新对象,也就是实例(如果没有手动返回其他的对象)
我在winter大神的重学前端专栏中,看到了比较符合我心意的,同时也是符合原理的描述:
• 以构造器的prototype属性为原型,创建新对象;
• 将this(也就是上一句中的新对象)和调用参数传给构造器,执行;
• 如果构造器没有手动返回对象,则返回第一步创建的新对象,如果有,则舍弃掉第一步创建的新对象,返回手动return的对象。
bind的话就是这样:
- 把调用bind()的函数(以后统称为初试函数)中的this指向绑定到某个对象上,bind的第二个及其以后的参数作为作为 初始函数的 参数,bind()执行完返回一个新的函数。
- 新返回的函数如果用 new 字符来调用的话,那么之前this指向绑定到某个对象上 将会失效,并且初始函数中的this指向绑定到 new调用的 函数实例上。函数实例上还可以调用初始函数的原型上的方法
本文源码: 在github 我的手写polyfily 上 ,欢迎star。