Mark24
记录灵感、技术、思考
JavaScript中this指向问题
一、this的默认指向问题
简单的概括:
this指向谁,取决于它的直接调用者,调用者是谁就是谁。
没有调用者,this指向 全局 ,浏览器中是 window
箭头函数的this, 取决于他外面第一个不是箭头函数的this。 this一旦绑定了上下文,不会被改变。
function test() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(test()()()) // window
二、this 存在的深层次分析
this
指向谁是在运行中决定的,this
其实是一个当前函数记录当前所属环境对象的一个指针,可以理解为一个上下文变量,this
指向的对象,包含了可以访问的属性和变量,相当于作用域的作用。
三、更改this指向的方法
- 方法有
call, apply, bind
- call和apply区别
func.apply(<运行中的this>, [argsArray])
function.call(<运行在的this>, arg1, arg2, ...)
call()
方法的作用和 apply()
方法类似,区别就是call()
方法接受的是参数列表,而apply()
方法接受的是一个参数数组。
- bind
bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数。
var arr=[1,10,5,8,12];
var max=Math.max.bind(null,arr[0],arr[1],arr[2],arr[3])
console.log(max(arr[4])); //12,分两次传参
参考:
四、手写模拟 apply/call/bind
模拟call
Function.prototype.myCall=function(context=window,...args){
console.log('----mycall this')
console.log(this) // 会输出为 f
console.log('---------')
// this,就是未来的函数f,比如他会调用 f.myCall(window, 其他参数),这里this就是f
// 相当于换了一个调用对象,帮他调用
context.f = this;
const res = context.f(...args);
delete context.f;
return res
}
function f(num){
console.log(this, num)
}
var obj={
a:1
}
f.call(obj,10);
f.myCall(obj,10);
console.log(obj)
模拟 apply
Function.prototype.myApply=function(context=window,args){
context.f = this;
const res = context.f(...args);
delete context.f;
return res
}
function f(num){
console.log(this,num)
}
let obj={
a:1
}
f.apply(obj,[10]);
f.myApply(obj,[10]);
console.log(obj)
模拟bind
Function.prototype.myBind=function(context=window, ...outerArgs){
const _this = this; // _this就是 f
console.log('position 1',_this)
return function(...innerArgs){
console.log('position 2',this)
_this.call(context,...outerArgs.concat(innerArgs))
}
}
let obj = {a:1}
function f(number){
console.log(this,number)
}
f1 = f.bind(obj,10);
f2 = f.myBind(obj,10);
f1();
f2();