标签:eof 查找 prot 并且 new this指针 行修改 nts array
<script>
// 分析: 相比于call和apply,bind的返回的是一个函数,并且这个函数完成的任务与apply相同。
//这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
//另外由于返回的是一个函数,要考虑这个返回函数作为构造函数被new时的this指针变化,并且保留原型的属性
Function.prototype.myBind = function(thisArg , ...args){// ...自定义名 代表剩余参数
let self = this //为了区分两种this的上下文,先将指向调用者的this保存在self中,
let fn = function(){ //把fn当作返回函数去制造
self.apply(this instanceof self ? this : thisArg , args.concat(Array.prototype.slice.call(arguments)))//借用数组原型上的slice,复制一份
//这个新函数的任务,是将this指向第一个参数,其他参数作为新函数的参数,并且还得接受其他参数得传入(这个新函数要模仿调用者)
//为了区分fn被new时和正常执行得不同,这里需要用instanceof加一层判断
// 1. fn函数被当作构造函数,被new运算
//那么fn中的this指向new出来的实例,也就是说这个新对象是调用者原型的一个实例(this.__proto__ === self.prototype)
//instanceof 判断成立
//根据原型链原理,优先调用自己的属性,再去原型链上查找。为了不丢失实例自身的属性,那么这个apply的第一个参数就只能是new出来的实例,也就是被new时的this
// 2. fn被正常调用
//默认调用者不在原型链上,也就不需要考虑原型链的要求。直接使用apply将this指向bind的第一个参数,将其他的参数作为新函数的实参。
//这里考虑到fn函数也需要接收参数(arguments),所以需要将 bind剩余的实参和fn函数接收的参数进行拼接 成为新的参数数组
}
// 这时候自己写得fn的prototype指向的是终端原型,因为fn是按调用者的样子造出来的,但是只有调用者的属性,缺少调用者原型上的属性,不够全面。
//所以将要将fn链接到调用者的原型链上去
fn.prototype = Object.create(self.prototype)
//首先我们是想将调用者得prototype直接当作fn得原型,也就是fn.prototype = this.prototype 但是这个写法使得两者指向了同一个地址,会有一定风险。
//也就是说当我们对fn.prototype进行修改时,会影响到self.prototype得属性。所以不如将self.prototype得一个实例当作fn得原型,就解决了这个问题。
return fn
}
//测试
const obj = { name: ‘i am cj‘ }
function foo() {
console.log(this.name)
console.log(arguments)
}
foo.myBind(obj, ‘a‘, ‘b‘, ‘c‘)()
</script>
标签:eof 查找 prot 并且 new this指针 行修改 nts array
原文地址:https://www.cnblogs.com/620chang/p/12781439.html