(五-1)this相关例题

执行环境

JS代码有三种运行环境

  1. Global Code : JavaScript代码开始运行的默认环境 this=> window
  2. Function Code: 代码进入一个JavaScript函数 this => 调用函数的对象
  3. Eval Code : 使用eval()执行代码

案例分析可以,很显然上述代码都是运行在Global Code环境中。而 obj中的this是根据代码的执行动态确定的。
当执行到console.log(obj.b1);时,如果此时b1对应的值是一个函数的话,那么函数中的this就是obj。而b1的值是this.a当获取 obj.b1时,是在全局执行环境下运行的,因此thiswindow

对象是没有this的,this是执行上下文里面的一个属性。因此有this的都有:全局执行环境、函数执行环境和eval执行环境。this的值可以是一个对象

经典案例请点击这里查看

注意:以下代码全基于浏览器非严格模式运行
咱先定义一个全局变量a,后面所有的示例都假定此全局变量已存在:

var a = 0;

案例一 :

// demo1
var obj =  {
  a: 1,
  b1: this.a,
  b2: () => this.a,
};

console.log(obj.b1);  
console.log(obj.b2());  

【运行结果】

0
0

案例二

// demo2
(function fn(){
  var a = 2;
  console.log(this.a); 

  const subf = ()=>this.a;
  console.log(subf()); 
})()

立即执行函数在全局环境下执行,函数中的thiswindow
【运行结果】

0
0

案例三

// demo3
var obj2 =  {
  a: 3,
  b1: function(){ return this.a;}, // b1: 0x99
  b2: function(){ return ()=>this.a}, // b2: 0x88
};
console.log(obj2.b1());  
console.log(obj2.b2()());  

obj2对象的b1对应的是一个函数,函数的this就是调用此函数的对象即obj2
【运行结果】

3
3

这个示例中箭头函数外的this是哪个?我们在箭头函数外面加个this.a看看:

var obj2 =  {
  a: 3,
  b1: function(){ return this.a;}, // b1:0x99
  b2: function(){ return ()=>this.a}, // b2: 0x88   b2()--> 0x77
};
console.log(obj2.b1());  
console.log(obj2.b2()());   // 0x77()

箭头函数没有自己this,因此箭头函数内的this就是箭头函数外的那个this
【运行结果】

3
3

案例四

// demo4
var obj4 =  {
  a: 4,
  b1: function(){ return this.a;},
  b2: function(){ return ()=> () => () => this.a},
};
console.log(obj4.b1()); 
console.log(obj4.b2()()()()); 

运行结果:

4
4

案例五

// demo5
function f0() {
  var a = 5;

  setTimeout(function() {
    var b1 = this.a;
    console.log(b1); 
  }, 100);

  setTimeout(function() {
    var b2 = ()=> this.a;
    console.log(b2);  
  }, 200);
}

f0(); 

setTimeout中的那个function运行于全局环境下,因此里面的this指向window。而箭头函数没有自己的this,所以第二个setTimeout中箭头函数的this也指向window.
【运行结果】

0
0

那么setTimeout的第一个参数使用箭头函数会是个什么情况?看下一个示例

案例六

// demo6
function f1() {
  console.log(this.a); // 0
  setTimeout(() => {
    console.log(this.a);  // 0
  }, 100);
}
f1(); 

f1()在全局环境下执行, 里面的this是window即console.log(this.a);结果为0。

这里箭头函数作为setTimeout的第一个参数,箭头函数外面的那个this是谁?把箭头函数换成this.fn():

function f1() {
  console.log(this.a); // 0
  setTimeout(this.fn() , 100); 
}

我们这里不用了解this.fn()有什么功能,看到它我们就会明白了this.fn()中的this和前面一行中的this.a中的this是同一个this。

【扩展一下】

// 这样执行
f1.call({a: 7});  // 7  7

结果分析:

// demo6
function f1() {
  console.log(this.a);   // 因为通过call对this的绑定,f1中的this指向 {a: 7}
  setTimeout(() => {
    console.log(this.a);  // 同样这里this指向 {a: 7}
  }, 100);
}

同理:

var bindf1 = f1.bind({a: 8}); 
bindf1(); // 8 8

箭头函数没有自己的this,箭头函数中用this和普通语句中的this没什么区别,所以,你知道非箭头函数下怎么用this,就知道箭头函数下怎么用this。
关于 “箭头函数对this固定化,箭头函数中的this绑定定义时所在的作用域,箭头函数不能通过 call() 或 apply() 方法绑定this” 等描述,都源于箭头函数没有自己的this。

案例七

var a = 1
var obj = {
  a: 2,
  test: () => {
    console.log(this.a)
  }
}
obj.test()

【分析】:obj.test(),是在所在的作用域是全局作用域,因此obj里面的thiswindow, 而testobj里面的一个箭头函数,箭头函数没有自己的this,因此这里的this就是离他最近的即obj所在的作用域的this,也就是window
【运行结果:】

1

var a = 1
var obj = {
  a: 2,
  innerObj: {
    a: 3,
    test: () => {
      console.log(this.a)
    }
  }
}
obj.innerObj.test()

【要知道的】:

对象是没有this的,this是执行上下文里面的一个属性。因此有this的都有:全局执行环境、函数执行环境和eval执行环境。this的值可以是一个对象

【分析】:
obj.innerObj.test()是在全局环境下运行的。所以obj里面的this指向的是window
innerObjobj里面的一个对象,(对象是没有this的)
innerObjobj使用的this都是全局执行环境下的thiswindow。所以innerObj里面的thiswindow
testinnerObj里面的一个箭头函数,箭头函数是没有自己的this,因此它使用的是innerObj里面的this,即window

实际上 objinnerObj、以及 test箭头函数使用的都是全局作用域下的this

【运行结果】:

1

var a = 1
var obj = {
  a: 2,
  test:function(){
    console.log(this.a)
  }
}

obj.test()

【分析】:
obj.test运行在全局环境下,obj里面的this是window。 test是obj里面的一个函数,(函数是有自己的this,且是在调用时确定)。这里是通过obj来调用test,因此test里面的this就是obj
【运行结果】:

2

var a = 1
var obj = {
  a: 2,
  test:function(){
    a: 3
    console.log(this.a)
    var arrFoo = () => {
      console.log(this.a)
    }
    arrFoo()
  }
}
obj.test()

【分析】:
obj里面的thiswindow
test函数里面的thisobj,所以第一次打印console.log(this.a)是全局对象里面的2
arrFoo是箭头函数,没有自己的this,它使用的是距离它最近的作用域里面的this,即test里面的this
【运行结果】:

2
2

案例八:箭头函数中的this指向

function a() {
  function b() {
    console.log(this === window)  
    var c = () => {
      console.log(this)  
    }
    return c()
  }
  return b()
}
a()

【分析】:
a()里面的thiswindow
b()虽然是在a()里面调用,但是在调用时,是“纯函数的调用”,前面没有任何引用即b()。所以b()里面的thiswindow。而在b()里面定义的箭头函数c()。不管他在哪里调用,都没有自己的this,因此箭头函数中的this一定就是b()里面的this, 即window.(和箭头函数在哪里调用,如何调用都没有关系)
【运行结果】:

true
Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}

var obj = {
  a: 'xxx'
}

function a() {
  function b() {
    console.log(this === obj) 
    var c = () => {
      console.log(this)  
    }
    return c()
  }
  b.call(obj)
}
a()

【分析】:
a()里面的thiswindow
b()里面的thisobj
c()里面的this等于b()里面的thisobj

【运行结果:】

true
{a: “xxx”}

案例九:立即执行函数中的this

立即执行函数中的this始终指向window

n = 0  // 全局下的b
var obj = {
  n: 'xxx'
}
function a() {
  console.log('a()里面的this是 =>', this)
  function b() {
    console.log('b()里面的this是 =>', this);
    (function(){console.log('立即执行函数里面的this是 =>',this)})() // b()里面的一个立即执行函数
  }
  b.call(obj)
}
a.call(obj)

【分析】:
a()里面的this是 obj
b()里面的this是 obj
b()里面立即执行函数的this是window。(因为立即执行函数是有系统自动调用的)
【执行结果】:

a()里面的this是 =>{n: “xxx”}
b()里面的this是 => {n: “xxx”}
立即执行函数里面的this是 => Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}

var a = 1
var obj = {
  a: 2,
  test: function () {
    setTimeout(function () {
      console.log(this.a)
    }, 1000)
  }
}
obj.test()

【分析:】
test()里面的thisobj
setTimeout里面的函数是有系统调用的,因此thiswindow
【运行结果】:

1

var a = 1
var obj = {
  a: 2,
  test: function () {
    setTimeout(() => {
      console.log(this.a)
    }, 1000)
  }
}
obj.test()

【分析】:
test()里面的thisobj
setTimeout里面的箭头函数是没有this的,即使箭头函数也是由系统自动调用,但是它没有自己的this,因此箭头函数里面使用到的this都是距离它最近的作用域中的thistest()里面的this
【运行结果】:

2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值