你不懂JS: this 与对象原型 第二章: this豁然开朗! 在第一章中,我们摒弃了种种对this的误解,并且学习了this是一个完全根据调用点(函数是如何被调用的)而为每次函数调用建立的绑定。 调用点(Call-site) 为了理解this绑定,我们不得不理解调用点:函数在代码中被调用的位置(不是被声明的位置)。我们必须考察调用点来回答这个问题:这个this指向什么? 一般来说寻找调用点就是:“找到一个函数是在哪里被调用的”,但不总是那么简单,比如某些特定的编码模式会使 真正的 调用点变得不那么明确。 考虑 调用栈(call-stack) (使我们到达当前执行位置而被调用的所有方法的堆栈)是十分重要的。我们关心的调用点就位于当前执行中的函数 之前 的调用。 我们来展示一下调用栈和调用点: function baz() { // 调用栈是: `baz` // 我们的调用点是global scope(全局作用域) console.log( "baz" ); bar(); // `bar` // 我们的调用点位于`baz` console.log( "bar" ); foo(); // `bar` -> `foo` // 我们的调用点位于`bar` console.log( "foo" ); } baz(); // 。与使用4种标准的this规则不同的是,箭头函数从封闭它的(function或global)作用域采用this绑定。 我们来展示一下箭头函数的词法作用域: function foo() { // 返回一个arrow function return (a) => { // 这里的`this`是词法上从`foo()`采用 console.log( this.a ); }; } var obj1 = { a: 2 }; var obj2 = { a: 3 }; var bar = foo.call( obj1 ); bar.call( obj2 ); // 2, 不是3! 在foo()中创建的箭头函数在词法上捕获foo()调用时的this,不管它是什么。因为foo()被this绑定到obj1,bar(被返回的箭头函数的一个引用)也将会被this绑定到obj1。一个箭头函数的词法绑定是不能被覆盖的(就连new也不行!)。 最常见的用法是用于回调,比如事件处理器或计时器: function foo() { setTimeout(() => { // 这里的`this`是词法上从`foo()`采用 console.log( this.a ); },100); } var obj = { a: 2 }; foo.call( obj ); // 2 虽然箭头函数提供除了使用bind(..)外,另外一种在函数上来确保this的方式,这看起来很吸引人,但重要的是要注意它们本质是用被广泛理解的词法作用域来禁止了传统的this机制。在ES6之前,我们为此已经有了相当常用的模式,这些模式几乎和ES6的箭头函数的精神没有区别: function foo() { var self = this; // 词法上捕获`this` setTimeout( function(){ console.log( self.a ); }, 100 ); } var obj = { a: 2 }; foo.call( obj ); // 2 虽然对不想用bind(..)的人来说self = this和箭头函数都是看起来不错的“解决方案”,但它们实质上逃避了this而非理解和接受它。 如果你发现你在写this风格的代码,但是大多数或全部时候,你都用词法上的self = this或箭头函数“技巧”抵御this机制,那么也许你应该: 仅使用词法作用域并忘掉虚伪的this风格代码。 完全接受this风格机制,包括在必要的时候使用bind(..),并尝试避开self = this和箭头函数的“词法this”技巧。 一个程序可以有效地同时利用两种风格的代码(词法和this),但是在同一个函数内部,特别是对同种类型的查找,混合这两种机制通常是自找很难维护的代码,而且可能是聪明过了头。 复习 为执行中的函数判定this绑定需要找到这个函数的直接调用点。找到之后,4种规则将会以 这个 优先顺序施用于调用点: 被new调用?使用新构建的对象。 被call或apply(或 bind)调用?使用指定的对象。 被持有调用的环境对象调用?使用那个环境对象。 默认:strict mode下是undefined,否则就是全局对象。 小心偶然或不经意的 默认绑定 规则调用。如果你想“安全”地忽略this绑定,一个像ø = Object.create(null)这样的“DMZ”对象是一个很好的占位值,来保护global对象不受意外的副作用影响。 与这4种绑定规则不同,ES6的箭头方法使用词法作用域来决定this绑定,这意味着它们采用封闭他们的函数调用作为this绑定(无论它是什么)。它们实质上是ES6之前的self = this代码的语法替代品。

this 指向问题的更多相关文章

  1. C语言中 指向函数的指针 简介

    引子:在学习CPrimerPlus的第十四章的14.13节中,遇到了如下三行文字,是有关指向函数的指针的,把我搞晕了. char * fump(); //返回指向char的指针的函数 char (* ...

  2. JS this指向

    正常模式 在正常模式下独立函数的的 this 指向 undefined 或 window. <script type="text/javascript"> functi ...

  3. java多态性,父类引用指向子类对象

    父类引用指向子类对象指的是: 例如父类Animal,子类Cat,Dog.其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类. Animal animal = new C ...

  4. 【javascript 技巧】谈谈setTimeout的作用域以及this的指向问题

    setTimeout的用法详见:http://www.w3school.com.cn/htmldom/met_win_settimeout.asp 是的,setTimeout的常见用法是让某个方法延迟 ...

  5. what's this? 浅谈js中this的指向问题

    刚刚学习js的朋友可能和我一样,看到代码中的this总是一脸懵逼,不知道this到底指向谁.经过一段时间的了解,我想跟大家分享下自己的理解. 何时出现this 函数在调用的时候,会自动获得两个特殊变量 ...

  6. EC笔记,第二部分:10.让=返回指向*this的引用

    Effective C++ 学习笔记 10 让=返回指向*this的引用 Table of Contents 1. 原因 2. 建议:在没有充分理由标新立异前,最好的做法是遵从传统. –by SkyF ...

  7. JavaScript中this指针指向的彻底理解

    this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象 这一点与函数中自由变量Action-varibal不同 var ...

  8. JavaScript中this指向的简单理解

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  9. 12-返回指针的函数&&指向函数的指针

    前言 接下来我只讲指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针   一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回 ...

  10. 彻底理解js中this的指向,不必硬背。

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

随机推荐

  1. Odoo附件传输

    转载请注明原文地址:https://www.cnblogs.com/cnodoo/p/9307319.html  一:odoo后端上传附件 odoo中的ir.attachment模型是附件模型,可以用 ...

  2. (mac系统下)mysql 入门

    1.安装好mysql之后并且服务启动,系统偏好设置里有启动mysql服务的按钮 看到running表示可用 2.通过终端访问mysql 先到mysql的路径下(默认安装没有配置环境变量):cd /us ...

  3. JavaScript基础注意点

    1.每个语句结尾一定加上分号 2.JavaScript本身对嵌套{ }的层级没有限制,但是过多的嵌套无疑会大大增加看懂代码的难度.遇到这种情况,需要把部分代码抽出来,作为函数来调用,这样可以减少代码的 ...

  4. 人人都是产品经理<1.0>

    用了大概2个月的时间,细细的读完了<人人都是产品经理>这本书,受益良多,期间也做了一些笔记,都在前面的博客————products系列中... 当然,更多的收获,还是沉滞在书中的注释,以及 ...

  5. array_sum(),array_product()的使用

    这两个函数在你处理数据的时候,相信会很有用处. 一个是处理数组所有值的和,一个是所有值的乘积.写这个随笔就是强调下,有特殊的情况需要注意,以防以后的工作中,统计的时候出现错误. 举个例子: $a = ...

  6. CAN总线典型特征

    CAN总线典型特征 2016-04-12 20:36:54来源: eefocus 关键字:CAN总线  典型特征   收藏 评论(0) 分享到 微博 QQ 微信 LinkedIn CAN总线有如下基本 ...

  7. 编译最新的SQLite 3.8.4.3为一个DLL

    SQLite是一个小型数据库.特别适合于client应用程序使用,它的众多优点就不多说了.有兴趣的去搜索. 话说使用吧. 我们要使用.就须要调用它.如今一步一步来. 第一步:上SQLite官网http ...

  8. Junit测试中找不到junit.framework.testcase

    在使用Junit进行测试时,出现如下问题: 找不到junit.framework.testcase 解决方法: 选中项目->属性->Java构建路径->库->添加外部jar 在 ...

  9. Android应用安全之第三方SDK安全

    第三方sdk的包括广告.支付.统计.社交.推送,地图等类别,是广告商.支付公司.社交.推送平台,地图服务商等第三方服务公司为了便于应用开发人员使用其提供的服务而开发的工具包,封装了一些复杂的逻辑实现以 ...

  10. 20155235 《网络攻防》 实验五 MSF基础应用

    20155235 <网络攻防> 实验五 MSF基础应用 实验内容 一个主动攻击实践,如ms08_067; (1分) 一个针对浏览器的攻击,如ms11_050:(1分) 一个针对客户端的攻击 ...