关于this在浏览器中的指向


代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="div0"></div>
</body>
<script>
  window.id = 'window';
  document.getElementById('div0').onclick = function(){
    alert(this.id);
    var callback = function(){
      alert(this.id)
    }
    callback();
  };
</script>
</html>

第一个输出"div0"可以理解很正常,为何第二个输出的是"window",callback是内部的函数他应该和外部的this都隐式调用指向div0,为何外部指向div0,内部指向window?
于是尝试命令行运行:

window.name = "window"
var text = function(){
  name = "text";
  alert(this.name);
  var callback = function(){
    alert(this.name)
  }
  callback()
}
text()

结果输出两次"text"
两者矛盾了吧,已晕望大神指点


this 指向的是方法属性的所有者,第一个方法的所有者是DOM元素, 内部函数call由于没有申明所有者所以他的所有这是window


你描述的两种情况都可以佐证第一个this指向DOM,第二个this指向window
this关键是看执行环境, 第一次在DOM中,这个不需要太多解释; 第二次相当于window.callback(), 所以this指向window
你描述的第二种场景出现你理解的差异是因为name = "text";, 这一步赋值操作, 使得window.name = "text", 所以执行callback()会打出text


我觉得 callback 又不是外部那个function的属性,所以callback里的this不会指向到外面那个function那边去。

至于为什么第二个例子都是text呢???

亲,里面的name忘了var了,没var会被当成全局,不信你再试试window.name看还是不是"window"


关于你验证想法的例子楼上都说出错误了。
补充:
1.如果事件函数中有一个内部函数func,在事件内部调用func时,func函数内部this实际指向window。
2.this的隐式绑定是作为对象的方法调用时才能生效。
3.对于1.我们可以使用call方法来修正

window.id = 'window';
  document.getElementById('div0').onclick = function(){
    alert(this.id);
    var callback = function(){
      alert(this.id)
    }
    callback.call(this);
  };

window.name = "window";
var text = function() {
    // name 没有用 var(或者 let、const)限定,是全局变量,即 window.name
    name = "text";

    // 参考下面 ①
    alert(this.name);

    var callback = function() {
        // 这个 this 参考 ②
        alert(this.name);
    };

    // ② 非对象方法方式调用,里面的 this 是全局对象,即 window
    callback();
};

// ① 非对象方法方式调用,text() 内部的 this 是全局对象,即 window
text();

所以自始至终你都是在操作同一个 name,即 window.name。如果想要理解 this,可以改一下代码

window.name= "window";

var obj = {
    text: function() {
        // 这两个 this 指的 obj,参考 ①
        this.name = "text";
        alert(this.name);

        // callback 内部的 this 参考 ②
        // 为了使用这里的 this,即 obj,可以用一个局部变量缓存
        var _this = this;
        var callback = function() {
            // 输出 widnow.name
            alert(this.name);

            // 输出 obj.name
            alert(_this.name);
        };

        // ② 对方法调用,callback() 内部的 this 是全局对象,即 window
        callback();
    }
};

// ① 方法调用,text 内部的 this 是 obj
obj.text();

// 这里的 obj.name 已经在 obj.text() 中赋值为 "text" 了
alert(obj.name);

补充一下

上面都是用的 es5 语法,如果用 es6 的箭头函数,或者说 Lambda 语法,就不需要缓存 _this

现在不是所有浏览器都支持 es6 语法,所以实际使用的过程中一般需要通过 babel 之类的工具编译成 es5。这里提出来只是顺着这个问题的知识点,多一个参考答案。

var obj = {
    text() {
        this.name = "text";
        var callback = () => {
            // Lambda 不改变作用域,这里的 this 就是 obj
            // this.name 就是 "text"
            alert(this.name);
        };
    }
};
obj.text();



相关阅读:
在node.js里面可以使用window对象的方法吗
angularjs如何将字符串类型的时间格式化呢
bundle-loader解析import异于ES6 module
video标签怎么控制播放内容的宽高?
IE兼容 React
弹出提示窗口JS怎么设置弹出一次,假设多弹出也要把前者取消,让后者弹出一次?
前端如何掌握必须的http知识?
在pfsense中启动barnyard2失败
scrapy怎么设置返回码不是200换代理
为什么有的公司要求DBA禁止使用between?
Laravel 如何获取路由名称?
前后端分离中碰到跨域问题大家是怎么解决的?
阮一峰老师《ECMAScript 6入门》第一节中的疑问
定时器中this为什么会指向window
backbone排序问题,视图实时排序
vuex中的state值,在工具类模块中怎么获取?
怎样用yii2.0配合mongodb做后台的权限控制系统???
类方法里实现网络请求类单例的方法有些情况返回不了数据
mysql如何合并两张结构相同的数据表?
easyui1.5 datagrid中分页显示不正常,求教各位



快速导航

Copyright © 2016 phpStudy |