js中this指向问题

1、这两个代码的this指向让我懵逼了


2.1、

    var length = 10;
    function fn() {
        console.log(this.length);
    }
    var obj = {
        a: fn,
        length: 5,
        method: function (f) {
            //console.log(this===obj);//true
            f();
            //console.log(arguments)
            //arguments[0]();//
            //arguments[0].call(this);//
            //arguments[0].call(obj);//
        }
    };
    obj.method(obj.a);

2.2、

var name = 'out';
var obj = {
    name: 'in',
    prop: {
        name: 'inside',
        getName: function () {
            return this.name;
        }
    }
};

//console.log(obj.prop.getName());//
var test = obj.prop.getName;//
console.log(test());//


阅读 2.9k
4 个回答

this 绑定的是当前对象,必须是直接调用。

非严格模式下

var length = 10;
var fun = function(){
    console.log(this.length);
};
var obj = {
   length : 5,
   test : function(){
     console.log(this.length);
   },
   test2 : fun
}

obj.test(); //5
obj.test2(); //5
fun(); //10 非直接调用,this == undefined;非strict会调用window

严格模式下

'use strict';
var length = 10;
var fun = function(){
    console.log(this.length);
};
var obj = {
   length : 5,
   test : function(){
     console.log(this.length);
   },
   test2 : fun
}

obj.test(); //5
obj.test2(); //5
fun(); //跑出异常,this == undefined;undefined.length 错误

所以:

 var length = 10;
    function fn() {
        console.log(this.length);
    }
    var obj = {
        a: fn,
        length: 5,
        method: function (f) {
            //console.log(this===obj);//true
            f();
            //console.log(arguments)
            //arguments[0]();//
            //arguments[0].call(this);//
            //arguments[0].call(obj);//
        }
    };
    obj.a();
    /*
      5
      因为符合直接调用的模式
    */
    obj.method(obj.a);
    /*
      10
      这里的 obj.a 仅是当作值来传,值为 一个函数
      f();不符合 object.method(),严格模式下报错
    */
var name = 'out';
var obj = {
    name: 'in',
    prop: {
        name: 'inside',
        getName: function () {
            return this.name;
        }
    }
};

//console.log(obj.prop.getName());//
var test = obj.prop.getName;//
console.log(test());//
/*
    out
    和上边一样,也不是 object.method() 这种情况
*/

只要看最后是谁调用就行了
1.obj.method(obj.a)//这时obj.a和obj.a()是不一样的,obj.a是取这个属性的引用,而不是调用
等价于 obj.method(function(){})//所以执行的时候就是直接执行函数而,this指向全局或者undefined
2.一样的道理obj.prop.getName是取属性值的引用,obj.prop.getName()这样才是调用,所以这时候this还是指向全局或者undefined

1.this指向不看定义的时候在哪,而是看调用的时候指向。obj.method(obj.a)。那么调用的就是obj,而obj在全局作用域里面,所以this指向windowundefined(严格模式)。

2.调用的是testtest在全局作用域,所以name也是全局下的name。如果一定要修改这个指向,可以在这行:

    var test = obj.prop.getName.bind(obj);
    //或者
    var test = obj.prop.getName.bind(obj.prop);
    

再调用的时候就是in或者inside了

上面的大哥回答的很好了,我稍作一点补充
问题1,2实际是一个道理,咱们三段论的方式来看一下这个问题

  1. var a = function(){console.log(this)}; 当调用a()时,this指向的window,因为a()window.a()等价

  2. 承上var obj = {method: a};'与var obj = {};obj.method = a`等价

  3. 承上obj.methodwindow.obj.method等价,则调用obj.method()this指向window.obj

  4. 承上

var length = 10;
function fn() {
    console.log(this.length);
}
var obj = {
    a: fn,
    length: 5,
    method: function (f) {
        f();
    }
};
obj.method(obj.a);

其中

// 我们一般称f为回调函数
obj.method = function (f) {
  f();
}
obj.a = fn
obj.method(obj.a)
//等价
(function(f){f();})(fn);
//等价
fn();
//等价
window.fn();
//等价
console.log(window.length);// 10

题目二你可以尝试自己分析一下,如果有哪里说得不对也欢迎大家指出。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题