// 1.严格模式下,普通函数中,指向undefined
/* "use strict"
function foo(){
console.log(this)
}
foo()//undefined */
// 2.在普通模式下,普通函数中,谁调用这个函数,this就指向谁
/* function foo(){
console.log(this)
}
foo()//全局函数可以看成是window对象的方法,相当于是window调用 */
/* var obj={
name:"obj",
sayHello:function(){
console.log(this)
}
}
obj.sayHello()//obj调用,指向obj */
/* var age1="window"
let age2=10
var obj={
name:"obj",
sayHello:function(){
console.log(this)
}
}
console.log(window.age1) //window
console.log(window.age2) //undefined */
/* var name="window"
var obj={
name:"obj",
sayHello:function(){
console.log(this)
}
}
console.log(obj.name) //obj
obj.sayHello() //指向obj */
/* var name="window"
var obj={
name:"obj",
sayHello:function(){
return function(){
console.log(this.name)
}
}
}
obj.sayHello() //没有结果,返回的函数体没有执行
console.log(obj.sayHello()) //返回函数体
obj.sayHello()() //window */
/* var name="window"
var obj={
name:"obj",
sayHello:function(){
console.log(this.name)//obj
setTimeout(function(){//setTimeout是全局方法(window的方法)
console.log(this.name)//window
})
}
}
obj.sayHello() */
//3.箭头函数中的this指向
//指向定义这个箭头函数时所在环境中的this,在哪个地方定义,指向那个地方的this
/* var foo=()=>{
console.log(this)
}
foo()//window */
/* var name="window"
/* var obj={
name:"obj",
sayHello:()=>{
console.log(this.name)
}
}
//相当于下面的代码
var obj={}
obj.name="obj"
obj.sayHello=()=>{
console.log(this.name)
}
obj.sayHello()//window */
/* var name="window"
var obj={
name:"obj",
sayHello:function(){
return ()=>{
console.log(this.name)
}
}
}
obj.sayHello()() //obj,所在的环境为obj */
/* var name="window"
var obj={
name:"obj",
sayHello:()=>{
console.log(this)
return ()=>{
console.log(this.name)
}
}
}
obj.sayHello()() //window */
/* var name="window"
var obj={
name:"obj",
sayHello:()=>{
console.log(this)//window
return function(){
console.log(this.name)//window
}
}
}
obj.sayHello()() */
/* var name="window"
var obj={
name:"obj",
sayHello:function(){
console.log(this)//{name: "obj", sayHello: ƒ}
return ()=>{
console.log(this.name)//obj
}
}
}
obj.sayHello()() */
4.补充(补充部分的参考网址:https://juejin.im/post/5c96d0c751882511c832ff7b)
补充1(隐式绑定):对象属性链中只有最后一层会影响到调用位置。
function sayHi(){
console.log('Hello,', this.name);
}
var person2 = {
name: 'Christina',
sayHi: sayHi
}
var person1 = {
name: 'YvetteLau',
friend: person2
}
person1.friend.sayHi();//Hello, Christina.
隐式绑定有一个大陷阱,绑定很容易丢失(或者说容易给我们造成误导,我们以为this指向的是什么,但是实际上并非如此).
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'YvetteLau',
sayHi: sayHi
}
var name = 'Wiliam';
var Hi = person.sayHi;
Hi();
Hi直接指向了sayHi的引用,在调用的时候,跟person没有半毛钱的关系
隐式绑定的丢失是发生在回调函数中(事件回调也是其中一种),我们来看下面一个例子:
function sayHi(){
console.log('Hello,', this.name);
}
var person1 = {
name: 'YvetteLau',
sayHi: function(){
setTimeout(function(){
console.log('Hello,',this.name);
})
}
}
var person2 = {
name: 'Christina',
sayHi: sayHi
}
var name='Wiliam';
person1.sayHi();//Hello,Wiliam
setTimeout(person2.sayHi,100);//Hello,Wiliam
setTimeout(function(){
person2.sayHi();
},200);//Hello, Christina
注: person1.sayHi()和person2.sayHi不一样,一个是隐式绑定,一个是相当于是变量
第一条输出很容易理解,setTimeout的回调函数中,this使用的是默认绑定,非严格模式下,执行的是全局对象
第二条输出是不是有点迷惑了?说好XXX.fun()的时候,fun中的this指向的是XXX呢,为什么这次却不是这样了!Why?
其实这里我们可以这样理解: setTimeout(fn,delay){ fn(); },相当于是将person2.sayHi赋值给了一个变量,最后执行了变量,这个时候,sayHi中的this显然和person2就没有关系了。
第三条虽然也是在setTimeout的回调中,但是我们可以看出,这是执行的是person2.sayHi()使用的是隐式绑定,因此这是this指向的是person2,跟当前的作用域没有任何关系。
补充2(显示绑定):显式绑定比较好理解,就是通过call,apply,bind的方式,显式的指定this所指向的对象。
call,apply和bind的第一个参数,就是对应函数的this所指向的对象。call和apply的作用一样,只是传参方式不同。call和apply都会执行对应的函数,而bind方法不会。
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'YvetteLau',
sayHi: sayHi
}
var name = 'Wiliam';
var Hi = person.sayHi;
Hi.call(person); //Hi.apply(person)
输出的结果为: Hello, YvetteLau. 因为使用硬绑定明确将this绑定在了person上。
那么,使用了硬绑定,是不是意味着不会出现隐式绑定所遇到的绑定丢失呢?显然不是这样的,不信,继续往下看。
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'YvetteLau',
sayHi: sayHi
}
var name = 'Wiliam';
var Hi = function(fn) {
fn();
}
Hi.call(person, person.sayHi); //Hello, Wiliam
输出的结果是 Hello, Wiliam. 原因很简单,Hi.call(person, person.sayHi)的确是将this绑定到Hi中的this了。但是在执行fn的时候,相当于直接调用了sayHi方法(记住: person.sayHi已经被赋值给fn了,隐式绑定也丢了),没有指定this的值,对应的是默认绑定。
现在,我们希望绑定不会丢失,要怎么做?很简单,调用fn的时候,也给它硬绑定。
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'YvetteLau',
sayHi: sayHi
}
var name = 'Wiliam';
var Hi = function(fn) {
fn.call(this);
}
Hi.call(person, person.sayHi);//Hello, YvetteLau
js中this的指向问题
最新推荐文章于 2023-04-09 08:28:47 发布