为什么这里的this都指向window??

非严格模式下,为什么this都指向window??

    function fn(){
      console.log(this);
    }
    var oo={
      sum:function(){
        fn();
      }
    }
    oo.sum();
    var o = oo.sum
    o()

题目来源及自己的思路

不是说看函数值前面是否有”.“么?
有点”.“,this指向调用函数那个
没有指向window

有点蒙逼啊

阅读 2.4k
3 个回答

稍微帮你把这段代码梳理一下:

// 这里你声明了一个函数fn,那么我声明的函数fn会有哪些调用方式呢(请看后文)?
function fn(){
  console.log(this);
}

// 这里你声明了一个oo对象,属性sum是一个方法(对象内属性是函数一般称为方法,跟普通声明的函数有所区分)
var oo = {
  sum: function() {
    // 这里在sum方法内部调用外部函数fn, 注意这里fn内的this指向跟sum方法内的this指向不要联想会有关联,目前这种调用方式毫无关联。
    fn();
  }
}

// 调用方法sum
oo.sum();

// 通过sum指向的函数引用来调用sum函数.
var o = oo.sum
o()

上面简单把语句注明作用从问题来看,题主应该对于函数内部this的指向有所疑惑。

由于在js中,this的指向与函数被调用的方式直接相关,所以只要了解了函数有哪些调用情况会改变this,那么我们就能很好地阅读代码时判断this指向。

我声明的函数fn会有哪些调用方式呢?

function fn(){
  console.log(this);
}
  1. 正常情况我们直接 fn() 调用, 内部this指向运行环境的全局对象(在浏览器中就是window对象,在node环境中就是global对象);注意:而题主在方法sum内部就是这么调用的,所以不管你是怎么调用sum,而fn函数的调用方式没有发生变化,所以fn内部的this指向就不会发生变化。

    一个变种,我们将fn赋值给一个变量,正常调用情况的另一种形式,比如说

    var  c = fn; 
    c(); //这里fn的指向和第一条里面的指向是一致的。
  2. 但当我们将fn赋值给一个对象属性,方法调用,比如说

    var c = {}; 
    c.fn = fn;
    c.fn(); //这时候fn内部的this就会指向c这个对象, 这种情况我们就改变了fn的调用方式了
    // 再补充一下
    c['fn'](); //这种方式调用和用属性操作符dot是一致的,this同样指向调用对象,也就是c这个对象。
  3. 我们给fn显式的指明this;

    var c = {};
    fn.call(c); // 还有 fn.apply(c) 或者 fn.bind(c) 等等这种方式就指定了fn内部的this强制指向c这个参数
  4. 当我们把fn当成构造函数来用的时候,this指向新创建的实例对象

    var c = new fn(); //这时候内部的this会指向c这个对象实例

对于sum方法来说,

oo.sum(); //属于上面的第2种描述,但是它影响的只是sum函数内的this, 而无法影响到fn函数内。
var o = oo.sum;
o(); //属于上面的第一种情况,oo.sum是一个函数体 function() { fn();} 它的引用,你将引用赋给了o这个变量之后,就与oo对象不再有任何关系,o这个变量就相当于函数名,跟o()和fn()是一致的情况。

上面就是能够改变this的指向的4种情况,希望上述总结对题主有所帮助。

你可以这样写

var obj = {
    var1: 'obj',
    fn1: function(){
    console.log(this)
    }
}

obj.fn1()
// 此时this就指向了obj这个对象

image.png

在JavaScript中

this 代表运行时当前对象的引用

看你的代码,运行环境应该是在浏览器中(JS也能在NodeJS的环境中运行)
那么你sum方法里面对fn的调用是直接调用,直接调用不管你是在函数里面,还是在全局环境下,永远是windows

你看下这段代码,可以复制到控制台运行下,node环境会有不同的结果

console.log(this);

var obj = {
    fn: function(){
        console.log(this);
    }
};
obj.fn();

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