this的绑定规则
new绑定
函数是否在 new 中调用(new绑定),如果是,那么 this 绑定的是new中新创建的对象。
显式绑定
函数是否通过 call,apply 调用,或者使用了 bind ,那么this绑定的就是指定的对象。
隐式绑定
函数是否在某个上下文对象中调用,如果是的话,this 绑定的是那个上下文对象。一般是 obj.foo()。谁调用就指向谁。
默认绑定
1.如果以上三种绑定都不是,那么使用默认绑定。如果在严格模式下,则绑定到 undefined,否则绑定到全局对象
2.如果把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind, 这些值在调用时会被忽略,实际应用的是默认绑定规则。
3.箭头函数没有⾃⼰的 this,箭头函数的this在定义的时候,会继承⾃外层第⼀个普通函数的this
更改this的指向
Call()方法
调用另一个对象的方法,call()方法分别接受参数。
<script>
// JS原生手写call():
Function.prototype.myCall = function(context){
if(typeof context === undefined || typeof context === null){
console.log(context,"context")
context = window
}
const symbol = Symbol()
context[symbol] = this
const args = [...arguments].slice(1)
const result = context[symbol](...args)
delete context[symbol]
return result
}
</script>
bind()方法
1.bind 接收多个参数绑定到函数,参数单一传入。
2.bind每次执行产生一个新函数,call、apply 不会。
<script>
// JS原生手写Bind()函数
Function.prototype.myBind = function (content){
if(typeof content === undefined || typeof content ===null){
context = window
}
const _this = this
const args = [...arguments].slice(1)
// 返回一个函数,我们可以new F(),所有需要判断
return function F(){
if(this instanceof F) {
return new _this(...args,...arguments)
}
}
}
</script>
apply()方法
1.调用另一个对象的方法,apply() 方法接受数组形式的参数。
2.call ,bind 接收多个参数绑定到函数,参数单一传入,apply 接收方式为数组
<script>
// JS原生手写apply()方法
Function.prototype.myApply = function(context){
if(typeof context===undefined || typeof context === null){
context = window
}
const symbol = Symbol()
context[symbol] = this
let result
// 处理参数和call有区别
if(arguments[1]){
result = context[symbol](...arguments)
} else {
result = context[symbol]
}
delete context[symbol]
return result
}
</script>
总结
bind 返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过 new 的方式,我们先来说直接调用的方式 对于直接调用来说,这里选择了 apply 的方式实现,但是对于参数需要注意以下情况:因为 bind 可以实现类似这样的代码 f.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来,于是就有了这样的实现 args.concat(...arguments) 最后来说通过 new 的方式,在之前的章节中我们学习过如何判断 this,对于 new 的情况来说,不会被任何方式改变 this,所以对于这种情况我们需要忽略传入的 this