js函数部分(二)---this

JS中this指向小结

关于 this 的指向,记住最核心的一句话:哪个对象调用函数,函数里面的this指向哪个对象。

普通函数中调用

这个情况没特殊意外,就是指向全局对象-window

var username = 'cn'
function fn() {    
alert(this.username);
}
fu();//cn
let username = 'cn'
function fn() {    
alert(this.username);
}
fn();//undefined
window.username = 'cn'
function fn() { 
   alert(this.username);
}
fn();//cn

对象函数调用

this是一个特殊变量,它始终指向当前对象,

window.b = 2222
let obj = {    
a: 111,
fn: function () {   
     alert(this.a);//111      
     alert(this.b);//undefined   
      }
      }
obj.fn();

对象函数调用常见问题
1、示例一:

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};

xiaoming.age; // function xiaoming.age()
xiaoming.age(); // 今年调用是25,明年调用就变成26了

将函数分开写

function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};

xiaoming.age(); // 25, 正常结果
getAge(); // NaN,getAge()中,this指向全局对象window

var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN(在严格模式下会报错),要保证this指向正确,必须用obj.xxx()的形式调用!

重构方法:用var that = this;,你就可以放心地在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var that = this; // 在方法内部一开始就捕获this
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - that.birth; // 用that而不是this
        }
        return getAgeFromBirth();
    }
};

xiaoming.age(); // 25

2、示例二:在闭包函数中使用this对象常见问题
匿名函数的执行环境具有全局性,因此其this对象通常指向window

var name="The window";
var odject={
name:"My object",
GetNameFunc:function(){
return function(){
     return this.name;
     };
     }
  };
alter(object.GetNameFunc()());  //The window;
object.GetNameFunc();  //My object
(object.GetNameFunc=object.GetNameFunc)();  //The window ,
//赋值表达式是对函数的引用,return a=b;返回的是b,等同于执行了函数;

把外部作用域中的this对象保存到一个闭包能访问到的变量里,就可以让闭包访问该对象了

var name="The window";
var odject={
name:"My object",
GetNameFunc:function(){
return function(){
     var that=this;
     return this.name;
     };
     }
  };
alter(object.GetNameFunc()());  //My object;

构造函数调用

let TestClass=function(){   
 this.name='111';
 }
 let subClass=new TestClass();
 subClass.name='cn';
 console.log(subClass.name);//cn
 let subClass1=new TestClass();
 console.log(subClass1.name)//111

箭头函数

ES6 提供了箭头函数,增加了我们的开发效率,但是在箭头函数里面,没有 this ,箭头函数里面的 this 是继承外面的环境。

let obj={
  a:222,   
  fn:function(){      
        setTimeout(()=>{console.log(this.a)));   
         }
         };
obj.fn();//222
//传给 setTimeout 的是箭头函数,然后箭头函数里面没有 this ,所以要向上层作用域查找,在这个例子上, setTimeout 的上层作用域是 fn。
//而 fn 里面的 this 指向 obj ,所以 setTimeout 里面的箭头函数的 this ,指向 obj 。所以输出 222 。
let obj={  
  a:222,   
  fn:function(){        
    setTimeout(function(){console.log(this.a)})    }};
obj.fn();//undefined
//虽然 fn() 里面的 this 是指向 obj ,
//但是,传给 setTimeout 的是普通函数, this 指向是 window , window 下面没有 a ,所以这里输出 undefined。

call和apply

在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window,不过,我们还是可以控制this的指向的!
要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数;对普通函数调用,我们通常把this绑定为null。
用apply修复getAge()调用:

function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};

xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空

另一个与apply()类似的方法是call(),唯一区别是:
apply()把参数打包成Array再传入;
call()把参数按顺序传入。

Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5

小结

this这个 keyword非常的困惑,但是其实有一个好方法可以理解.

  1. 检查 ’ . ’ 左边是谁invoke 这个函数. 例如 xiaoming.age(); age函数里面有this, 然后 '. ’ 旁边是xiaoming , 那么this就是指向xiaoming了.
  2. 如果点旁边没有,那就检查有没有用到 bind, apply, call 这三种, 有的话就是调用此方法的对象.
  3. 如果上面两个都没有就检查代码里面有没有用到new 这个keyword, 有的话那就是指向new旁边的函数对象.
  4. 上面三个都没有, 检查是不是有arrow function, 有arrow function的话就是, 那么指向是arrow function的lexical binding 的对象. 就是她的parent.
  5. 全部都没有如果不是strict mode那就是window对象了… strict就是 error (undefined).
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值