笔记-JS this指向


哪个对象调用函数,函数里面的this指向哪个对象。

普通函数调用
var name="tiger";
function Animal(){
	var name="cat";
	console.log(this.name);
}
Animal();		//输出结果:tiger

window对象调用Animal函数,this指向window对象。

let name="tiger";
function Animal(){
	console.log(this.name);
}
Animal();		//输出结果:undefined

使用let声明,name是局部变量,window对象下没有name属性,所以输出结果为undefined。

对象函数调用
window.b=111;
let obj={
	a:222,
	fn:function(){
		console.log(this.a);	//输出结果:222
		console.log(this.b);	//输出结果:undefined
	}
}
obj.fn();

obj对象调用函数,this指向obj对象。

let obj1={
	a:111;
}
let obj2={
	a:222;
	fn:function(){
		console.log(this.a);
	}
}
obj1.fn=obj2.fn;
obj1.fn();		//输出结果:111

虽然obj1.fn是从obj2.fn赋值而来,但是调用函数的是obj1,所以this指向obj1.

构造函数调用
function Foo(){
	console.log(this);
}
var bar=new Foo();	//输出结果:Foo实例,this就是bar

函数作为构造函数使用new调用时,this绑定的是新创建的构造函数的实例。

使用new调用构造函数时,会依次执行下面的操作:
1.创建一个新对象;
2.构造函数的prototype被赋值给这个新对象的__proto__;
3.将新对象赋值给当前的this;
4.执行构造函数;
5.如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象,如果返回的不是对象将会被忽略;

采用call、apply、bind改变this
var name="tiger";
function Animal(){
	console.log(this.name);
}
Animal.call({name:"lion"})		//输出结果:lion

当使用call调用函数时,this被指向传入的对象。使用apply也可以达到相同的效果,但在实现上call和apply稍有不同。call方法接收的是参数列表,而apply方法接收的是一个参数数组。

func.call(thisArg,arg1,arg2,...);
func.apply(thisArg,[arg1,arg2,...]);

bind方法设置this为给定的值,并返回一个全新的函数,且在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。

func.bind(thisArg[,arg1[,arg2[,...]]]
var food={
	name:"汉堡",
	price:"5块钱",
	getPrice:function(place){
		console.log(place+this.price);
	}
}
food.getPrice("KFC")	//输出结果:KFC5块钱
var getPrice1=food.getPrice.bind({name:"鸡腿",price:"7块钱"},"肯德基")
getPrice1();

采用apply实现bind原理

// ES5 方式
Function.prototype.bind = Function.prototype.bind || function() {
    var self = this
    var rest1 = Array.prototype.slice.call(arguments)
    var context = rest1.shift()
    return function() {
        var rest2 = Array.prototype.slice.call(arguments)
        return self.apply(context, rest1.concat(rest2))
    }
}

// ES6 方式
Function.prototype.bind = Function.prototype.bind || function(...rest1) {
    const self = this
    const context = rest1.shift()
    return function(...rest2) {
        return self.apply(context, [...rest1, ...rest2])
    }
}

如果将null或undefined作为this的绑定对象传入call、apply、bind,这些值在调用时会被忽略,实际应用的是默认规则。

var a="hello";
function foo(){
	console.log(this,a);
}
foo.call(null);		//输出结果:hello

this绑定的优先级:构造函数绑定(new绑定)>call、apply、bind绑定(显示绑定)>对象函数调用(隐式绑定)>普通函数调用(默认绑定)

箭头函数

箭头函数里面没有this,箭头函数里面的this是继承外面的环境。

let obj={
	a:111,
	fn:function(){
		setTimeout(function(){console.log(this.a)});
	}
};
obj.fn();		//输出结果:undefinded

fn()里面的this是指向obj,但是传给setTimeout的是普通函数,this指向的是window,window下面没有a,所以这里输出undefined.

换成箭头函数

let obj={
	a:111,
	fn:function(){
		setTimeout(()=>{console.log(this.a)});
	}
};
obj.fn();		//111

传给setTimeout的是箭头函数,然后箭头函数里面没有this,所以要向上层作用域查找,setTimeout的上层作用域是fn,而fn里面的this指向obj,所以setTimeout里面箭头函数的this指向obj

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值