关于-this指向的理解
this
的不同应用场景,如何取值
作为普通函数被调用
使用 call apply bind
作为对象方法被调用
在class方法中调用
箭头函数 (找上级作用域)
this
取什么值是在函数执行的时候确认的,不是在函数定义的时候确认的
/*
this 指向 window 因为 他当做执行函数 执行函数会直接确认this指向
*/
/*
this 指向 当前对象 因为 箭头函数 作为回调函数来使用 只有当函数被调用的 时候才会触发 this指向
*/
const pepole = {
await(){
setTimeout(function (){
console.log(this);
})
setTimeout(() =>{
console.log(this);
})
}
}
call, apply, bind都是改变函数执行的上下文,说的直白点就是改变了函数this的指向。不同的是:call和apply改变了函数的this,并且执行了该函数,而bind是改变了函数的this,并返回一个函数,但不执行该函数。
call 内部实现原理
call()
方法调用一个函数, 其具有一个指定的 this
值和分别地提供的参数(参数的列表)。
注意:该方法的作用和 apply()
方法类似,只有一个区别,就是 call()
方法接受的是若干个参数的列表,而 apply()
方法接受的是一个包含多个参数的数组。
语法:
fun.call(thisArg[, arg1[, arg2[, ...]]])
参数:
thisArg
- 在 fun 函数运行时指定的 this 值
- 如果指定了 null 或者 undefined 则内部 this 指向 window
arg1, arg2, ...
- 指定的参数列表
Function.prototype.call = function(thisArg, args) { // this指向调用call的对象 if (typeof this !== 'function') { // 调用call的若不是函数则报错 throw new TypeError('Error') } thisArg = thisArg || window thisArg.fn = this // 将调用call函数的对象添加到thisArg的属性中 const result = thisArg.fn(...[...arguments].slice(1)) // 执行该属性 delete thisArg.fn // 删除该属性 return result }
apply 内部实现原理
apply()
方法调用一个函数, 其具有一个指定的 this
值,以及作为一个数组(或类似数组的对象)提供的参数。
注意:该方法的作用和 call()
方法类似,只有一个区别,就是 call()
方法接受的是若干个参数的列表,而 apply()
方法接受的是一个包含多个参数的数组。
语法:
fun.apply(thisArg, [argsArray])
参数:
thisArg
argsArray
apply()
与 call()
非常相似,不同之处在于提供参数的方式。apply()
使用参数数组而不是一组参数列表。例如:
fun.apply(this, ['eat', 'bananas'])
Function.prototype.apply = function(thisArg, args) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
thisArg = thisArg || window
thisArg.fn = this
let result
if(args) {
result = thisArg.fn(...args)
} else {
result = thisArg.fn()
}
delete thisArg.fn
return result
}
bind 内部实现原理
bind
后的函数会返回一个函数,而这个函数也可能被用来实例化
bind
方法后面有一对空格,所以得出结论bind返回的是一个函数必须调用才会执行 bind({x:20})()
语法:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
返回值:返回由指定的this值和初始化参数改造的原函数的拷贝。
Function.prototype.bind = function(thisArg) {
if(typeof this !== 'function'){
throw new TypeError(this + 'must be a function');
}
// 存储函数本身
const _this = this;
// 去除thisArg的其他参数 转成数组
const args = [...arguments].slice(1)
// 返回一个函数
const bound = function() {
// 可能返回了一个构造函数,我们可以 new F(),所以需要判断
if (this instanceof bound) {
return new _this(...args, ...arguments)
}
// apply修改this指向,把两个函数的参数合并传给thisArg函数,并执行thisArg函数,返回执行结果
return _this.apply(thisArg, args.concat(...arguments))
}
return bound
}
对 bind this 指向的 一些总结
bind this 指向问题 ,就是 谁调用,在哪里调用,this指向 就会在哪里 发送, 并且this 就会指向 他。
简单来说 就是 this 指向 是 根据自由变量来决定的 ,自由变量在他被调用 ,被使用的 时候 他会在 他的作用域来进行查找 这个当前 使用的 变量 ,然后根据 他 需要访问的变量 ,然后 来 使他这个 变量值进行 改变,this 指向的是在 哪里 进行调用 ,就会在哪个作用域中进行调用。
自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方查找!
this
指向的是当前对象。如果在全局范围内使用 this ,则指代当前页面 window 如果在函数中使用this
, 则this指代什么是根据当前函数是什么对象上调用。我们可以call
和apply
和bind
改变函数中this
的 具体指向
本作品采用《CC 协议》,转载必须注明作者和本文链接