this的各种指向和案例

this

this 的指向会被分为几种情况。

1. 全局环境下

console.log(this);	// window

2. 普通函数中的 this 指向全局

严格模式下指向 undefined。

function fn(){
	console.log(this);	// window
}
fn();
//嵌套函数也指向window

即使是嵌套的函数, this 也是指向全局对象

function outer() {
  function inner(){
    console.log(this);	// window 
  }
  inner();
};   
outer();

3. 通过对象调用, this 指向该对象

let obj = {
    name: "zhangsan",
    talk(){
       	console.log(this);	// 整个 obj 
    }
}
obj.talk();
 function foo() {
   console.log(this);
 }
foo();	// window
const obj = { name: "zhangsan" };
obj.talk = foo;
obj.talk();	// {name: "zhangsan"}

4. 事件监听器中的 this,指向事件源

btn.onclick = function(){
	console.log(this);		// <input type="button" value="click me">
}

5. 构造函数中的 this,指向 new 出来的实例对象

function Person(name) {
  this.name = name;
  console.log(this);	// {name:"zhangsan"}
}
let obj = new Person("zhangsan");

之前讲到 new 经历的4个步骤中,就提到了“绑定 this 到空对象”身上。

6. 箭头函数的 this 看声明

箭头函数的 this 指向取决于当前箭头函数声明的环境(执行上下文)。

执行上下文又分为:全局执行上下文、函数级 别上下文、eval 执行上下文。

因为箭头函数没有自己的 arguments 和 this,它内部的this 是由词法作用域上下文确定。(换句话说,箭头函数需要获取函数定义时所在的 EC 的 this,箭头函数定义在哪个作用域中,它的 this 就继承当前作用域 this 的指向。)

1. 定义在全局指向 window

let fn = () = >{console.log(this)}	// window

2. 对象中的箭头函数

var name = "小w";
let obj = {
  name: "zhangsan",
  talk: () => {
    console.log(this.name);	// 指向了 window,所以打印 小w
  }
}
obj.talk();
/*
	{} 不会生成作用域,即箭头函数声明在全局作用域中,this 指向全局
	通过 var 声明的变量会被认作是 window 的属性 即 var a = 5; window.a == a
*/

3. 普通函数中的箭头函数 看调用

function foo(){
  let bar = ()=>{
    console.log(this);	// window,箭头函数没有自己的 this,它的 this 使用 foo 的 this
  } 
  bar();
}
foo();

修改 this 的指向

三个方法都可以实现修改 this 指向:

  • call()

  • apply()

  • bind()

    改指向。call、apply 改变 this 指向的同时,立即自动调用函数。 bind 改变 this 指向并返回一个新函数,需要重新显式调用一次函数。

假设当前存在一个普通函数:

function talk() {
  console.log(this);	//普通函数,this 必定指向全局 window
  console.log(this.girlfriend); 	// undefined
}
talk();

如果再存在一个对象,让这个对象去调用这个函数,必定就指向该对象:

const obj = {name: "zhangsan"};
obj.talk = talk;
obj.talk();	// zhangsan

但这种写法并不友好,并且存在局限性,所以通常通过另外 3 种方法去修改 this 的指向。这三个方法都是 函数的方法。

语法:

  • fn.call(target)

  • fn.apply(target)

  • fn.bind(target)()

改变 this 指向

function foo() {
  console.log(this);
};
const obj = {
  name: "zhangsan"
};
foo.call(obj); 	// zhangsan
foo.apply(obj);	// zhangsan
foo.bind(obj)();	// zhangsan 

当有参数传入

  • fn.call(target, 20);

  • fn.apply(target, [20]);

  • fn.bind(target)(20);

function foo(a) {
  console.log(this, a);
};
const obj = {
  name: "zhangsan"
};
foo.call(obj, 1);
foo.apply(obj, [2]);
foo.bind(obj)(3);

总结:各种this实例结果及推理

img

普通函数看调用,箭头函数看声明环境,var声明的变量能提升为window对象的键

img

普通函数看调用,箭头函数看声明环境,不是var声明的不能变量能提升为window对象的键,所以number没有值为undefined

img

第一个this为普通函数内部 看调用,所以最后面zhangsan.talk调用,即为const zhangsan{}这个大的对象,所以this为const zhangsan{},

又因为箭头函数看声明环境,生命在普通函数内部,所以第二个this的值为普通函数的 调用对象,所以也是const zhangsan{}这个大对象

img

foo(){}为语法糖,为普通函数,有因为普通函数调用为person对象,所以内部的箭头函数this指向为对象person,即this.name为person.name的值

img

因为两个箭头函数都声明在全局中,即this指向的为window对象

img

person.say赋值给左侧的student.say,即student对象也拥有了say这个方法,并且该方法是箭头函数,即声明在全局中,所以调用say()方法时是指向window对象,即this.name为字符串“window”

 var name = 'john';
        var obj = {
            name: 'colin',
            prop: {
                name: 'rose',
                getname: function () {
                    return this.name;
                }
            }
        }
console.log(obj.prop.getname());//rose  //普通函数看调用 prop的name
var test = obj.prop.getname; 把函数赋值给text
console.log(test()); //john 调用函数 指向全局 name = john
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值