返回列表 发新帖

javaScript this指向问题详解

[复制链接]

6

主题

53

回帖

198

积分

小学生

Rank: 2

金币
110
好评
0
信誉
100

MT论坛新人

发表于 2023-4-21 21:55:29 来自手机  | 显示全部楼层 | 阅读模式  来自 广东
1.this指向的几条规律
在函数体中,非显式或隐式地简单调用函数时,在严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会被绑定到全局对象window/global 上。
一般使用new方法调用构造函数时,构造函数的this会被绑定到新创建的对象上。
一般通过call/apply/bind 方法显式调用函数时,函数体内的this会被绑定到指定参数的对象上。
一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上。
在箭头函数中,this的指向是由外层(函数或全局)作用域来决定的。
2.探究函数中的this
function f1(){
    console.log(this);
}
function f2(){
    'use strict'
    console.log(this);
}
f1();//window
f2();//undefined
示例1

var test = {
    value :100,
    fn:function(){
        console.log(this);           //window   
        console.log(this.value);     //undefined
        console.log(this.test.value) //100
    }
}
var test2 = test.fn;//赋值给test2后,test2仍然是在window的全局环境中执行的
test2();
示例2

var test = {
    value :100,
    fn:function(){
        console.log(this);           //{value: 100, fn: ƒ}
        console.log(this.value);     //100
    }
}
test.fn();//在test上调用fn()函数,this指向test
3.通过bind、call、apply改变this指向
var name = '张三',age = 26;
var obj = {
    name:'李四',
    age:this.age,
    fn:function(var1,var2){
        console.log(this.name + '年龄是'+this.age,'喜欢的运动:'+var1+',喜欢的水果:'+ var2);
    }
}
var data = {
    name:'王五',
    age : 22
}
obj.fn.call(data,'羽毛球','苹果');//王五年龄是22 喜欢的运动:羽毛球,喜欢的水果:苹果
obj.fn.apply(data,['羽毛球','苹果']);//王五年龄是22 喜欢的运动:羽毛球,喜欢的水果:苹果
obj.fn.bind(data,'羽毛球','苹果')();//王五年龄是22 喜欢的运动:羽毛球,喜欢的水果:苹果
bind返回的是一个函数,你必须调用它才会被执行。

4.构造函数和this
function Foo(){
    this.user = 'lucy';
    const o = {};
    return o;
}
var instance = new Foo();
console.log(instance.user);//undefined
以上示例 instance返回一个空对象

function Foo(){
    this.user = 'lucy';
    return 1;
}
var instance = new Foo();
console.log(instance.user);//lucy
以上示例 instance返回的是目标对象示例 this。

从以上两个示例,可以得出:

如果构造函数中显式返回一个值,且返回的是一个对象,那么this就指向这个返回的对象;如果返回的不是一个对象,那么this仍然指向实例。

5.箭头函数中的this
var foo = {
    fn:function(){
        setTimeout(function(){
            console.log(this);
        })
    }
}
console.log(foo.fn());
this指向window对象

var foo = {
    fn:function(){
        setTimeout(()=>{
            console.log(this);
        })
    }
}
console.log(foo.fn());
箭头函数使得this指向foo这个对象

箭头函数中this指向是由其所属函数或全局作用域决定的

6.this优先级
示例1

function foo(a){
    console.log(this.a);
}
var obj1 = {
    a:1,
    foo:foo
}
var obj2 = {
    a:2,
    foo:foo
}
obj1.foo.call(obj2);//2
obj2.foo.call(obj1);//1
call,apply的显示绑定一般来说优先级更高。

示例2

function foo(a){
    this.a = a;
}
var obj1 = {};
var bar = foo.bind(obj1);//将foo方法绑定到obj1对象中
bar(2);
console.log(obj1.a);//2
通过bind将bar函数中的this绑定为obj1对象。执行bar(2)后,obj1.a的值为2,即执行bar(2)后,obj1的对象为{a:2}

那我们再执行以下代码

var bar2 = new bar(3);
console.log(bar2.a)//3
被new调用的时候,返回的实例已经与obj1解绑了,也就是new绑定修改了bind绑定的this指向

示例3

function foo(){
    return a=>{
        console.log(this.a);
    }
}
var obj1 = {
    a:2
}
var obj2 = {
    a:3
}
var bar = foo.call(obj1);
console.log(bar.call(obj2));//2
由于foo中的this被绑定到了obj1,所以bar中的this也会被绑定到obj1上,箭头函数的绑定无法被修改。

实例4

var a = 123;
var foo = () => a =>{
    console.log(this.a)
}
var obj1 = {
    a:2
}
var obj2 = {
    a:3
}
var bar = foo.call(obj1);
console.log(bar.call(obj2));//123
foo修改为完全箭头函数,foo.call(obj1)无法改变this的指向。
回复

使用道具 举报

54

主题

648

回帖

1848

积分

高中生

Rank: 4

金币
147
好评
3
信誉
84

考神

发表于 2023-4-21 22:49:27 来自手机  | 显示全部楼层  来自 山东
是个大佬
回复

使用道具 举报

8

主题

3840

回帖

8798

积分

硕士生

Rank: 6Rank: 6

金币
2937
好评
6
信誉
96
发表于 2023-6-5 19:01:37 来自手机  | 显示全部楼层  来自 广西
感谢分享
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表