this指向判定,call,apply的应用

2016-10-09  本文已影响0人  Iswine

this的本质是任何函数创建时都会附带的隐藏参数,但因为不清楚其指向的问题,初学者往往犯迷糊,那么this到底指向谁呢?我们先来看几种情况(不讨论严格模式):

var obj = {
    "name": "obj1",
    "foo": function(){
        console.log(this);
        }
}
var fn = obj.foo;
fn();          //window
obj.foo();     //obj
fn.call(obj)   //obj

判断this的指向可以用call判断法:

fn() == window.fn() == fn.call(window)
obj.foo() == foo.call(obj);

call()和apply()均是用来指定this指向,传入参数的函数,常常用于高阶函数的计算之中,它们唯一的区别在于apply传入的是数组,而call传入的一个个参数。例:

function sum(x,y){
    return x+y;
}
sum.call(null,1,2);    //3
sum.apply(null,[1,2]);  //3

来看几道面试题:
1.以下代码输出什么?

var john = { 
  firstName: "John" 
}
function func() { 
  alert(this.firstName + ": hi!")
}
john.sayHi = func;
john.sayHi();   // John:hi!
// 因为john.sayHi() == john.sayHi.call(john),故答案如上;

2.下面代码输出什么,为什么?

func() 

function func() { 
  alert(this)
}      //window
//首先函数声明被提前,其次func() == func.call(window);

3.下面代码输出什么?

function fn0(){
    function fn(){
        console.log(this);
    }
    fn();
}
fn0();     //window,和上一题本质是一样的;

document.addEventListener('click', function(e){
    console.log(this);
    setTimeout(function(){
        console.log(this);
    }, 200);
}, false); 
//点击后,先输出document,再输出window;(setTimeout/setInterval中的this均指向window)   

4.下面代码输出什么,why?

var john = { 
  firstName: "John" 
}

function func() { 
  alert( this.firstName )
}
func.call(john) 
//John;  前面已解释;

5.下面代码输出什么,why?

var john = { 
  firstName: "John",
  surname: "Smith"
}

function func(a, b) { 
  alert( this[a] + ' ' + this[b] )
}
func.call(john, 'firstName', 'surname') 
//  John Smith;  同上

6.以下代码有什么问题,如何修改

var module= {
  bind: function(){
    $btn.on('click', function(){
      this.showMsg();
    })
  },
  
  showMsg: function(){
    console.log('饥人谷');
  }
}
module.bind();

由于事件触发中,this代表了$btn这个DOM节点,而不是程序员所期望的module对象,所以输出无效;
正确的应提前绑定this,改正后:

var module= {
  bind: function(){
    var that = this;
    $btn.on('click', function(){
    that.showMsg();
    })
  },
  
  showMsg: function(){
    console.log('饥人谷');
  }
}
module.bind();

7.下面代码输出什么? why?

obj = {
  go: function() { alert(this) }
}

obj.go();     // obj  执行环境为obj;

(obj.go)();   //obj;  被立即执行函数包裹,等价于obj.go();,环境依然为obj;

(a = obj.go)();   // window;  等价于(a = function(){alert(this)})()   此时环境为window;

(0 || obj.go)();   //window;

着重分析第四题,若题目为0 || (obj.go)()则输出obj
实际上,立即执行函数括号中已经生成了一个新的函数,而这个函数的执行环境是window,即已经变成了第三种情况。

上一篇 下一篇

猜你喜欢

热点阅读