JavaScript中this的四种调用模式

    this,即函数执行时的上下文环境,通常有四种调用模式:函数调用模式,方法调用模式,构造器调用模式,call/apply调用模式。

函数调用模式

就是普通函数的调用方式,此时this被绑定到window对象。

  • 最普通的函数调用
function fn1(){
    console.log(this);//window
}
fn1()
  • 函数嵌套
function fn1(){
    function fn2(){
        console.log(this);//window
    }
    fn2()
}
fn1()
  • 把函数赋值之后再调用
var a = 1;
var obj1 = {
    a:2,
    fn:function(){
        console.log(this.a);
    }
}
var fn1 = obj1.fn;
fn1();//1

obj1.fn是一个函数function(){console.log(this.a)},此时fn1就是不带任何修饰的函数调用,function(){console.log(this.a)}.call(undefined),按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:

如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

因此上面的this绑定的就是window,它也被称为隐性绑定。
如果你希望打印出2,可以修改fn1()fn1.call(obj1),显示地绑定this为obj1

  • 回调函数
var a = 1;
function f1(fn){
    fn();
    console.log(a);//1
}
f1(f2);

function f2(){
    var a = 2;
}

改写代码如下:

var a = 1;
function f1(){
    (function (){var a = 2})();
    console.log(a);//1
}
f1();

仍旧是最普通的函数调用,f1.call(undefined),this指向window,打印出的是全局的a。
借此,我们终于可以解释为什么setTimeout总是丢失this了,因为它也就是一个回调函数而已。

setTimeout(function() {
    console.log(this);//window
    function fn(){
        console.log(this);//window
    }
    fn();
}, 0);

总结:函数调用模式this指向window的全局对象

方法调用模式

    当一个函数被保存为对象的一个方法时,如果调用表达式包含一个提取属性的动作,那么它就是被当做一个方法来调用,此时的this被绑定到这个对象。

var a = 1;
var obj1 = {
   a:2,
   fn:function(){
      console.log(this.a);
   }
}
obj1.fn();//2    

此时的this是指obj1这个对象,obj1.fn()实际上是obj1.fn.call(obj1)事实上谁调用这个函数,this就是谁。补充一下,DOM对象绑定事件也属于方法调用模式,因此它绑定的this就是事件源DOM对象。如:

document.addEventListener('click', function(e){
    console.log(this);  //document
    setTimeout(function(){
        console.log(this); //window
    }, 200);
}, false);

点击页面,依次输出:document和window对象
解析:点击页面监听click事件属于方法调用,this指向事件源DOM对象,即document.click.apply(document),setTimeout内的函数属于回调函数,可以这么理解,function.call(null),所以this指向window。

总结:方法调用模式this指向调用者

构造器调用方式

    new一个函数时,实际上会创建一个连接到prototype成员的新对象,同时this会被绑定到那个新实例对象上。

function Person(name,age){
// 这里的this都指向实例
    this.name = name;
    this.age = age;
    this.sayAge = function(){
        console.log(this.age);
    }
}

var dot = new Person('Dot',2);
dot.sayAge();//2

总结:构造函数调用模式this指向被构造的实例对象

call/apply调用模式

    对象借用不属于该对象的方法(函数),即我们自定义this的指向。
语法: 
1、函数.apply(对象, [参数列表]) 
2、函数.call(对象, arg1,arg2,arg3…argn)

var fun = function(str) {
    this.status = str;
};
fun.prototype.getStatus = function() {
    alert(this.status);
};
var obj = {
    status: 1
};
fun.prototype.getStatus.apply(obj);
// obj对象冒充fun
//相当于 fun.prototype.getStatus.apply(obj, null); 

总结:this指向第一个参数


 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值