• Oh no....我的This又丢失了???
  • 为什么我用Class'实例化'出来的对象会相互影响??? ####这些问题都是因为JS的运行机制造成的。在JS中所有的一切都是对象,而this是对象的一个属性。在对象被调用时,this动态的根据上下文环境进行绑定,因此this和词法作用域没有关系。

一、何谓this

  1. this是函数执行上下文对象的一个属性,存在于运行时,而不是定义时,所以它和词法作用域没有必然的关系。
  2. 要使用this,首先需要考虑的是函数的调用环境而不是编写定义环境。它不指向函数本身,也不指向词法作用域。它由函数调用时发生在上下文环境的绑定而决定。
  3. 使用this要找函数的调用位置,而不是函数的声明位置。调用栈记录了函数的调用位置和顺序。通过调试工具可以查看调用栈,找出函数的调用位置。调用时使用了谁的上下文,this就指向谁。特别要注意的是回调函数传递的是引用,所以会丢失this。真正执行回调函数的位置决定了this的指向。
  4. bind把用来硬绑定函数执行的上下文,用于硬绑定this。(在React组件构造函数中显示的绑定This,防止丢失上下文环境)。除此之外,赋值表达式会传递函数的引用,它的调用位置会变成函数声明的位置。
  5. JS中Class对象的构造函数不是其它面向对象语言的构造函数,它是对已有函数的构造调用,本质上也是This的绑定。new关键字看上去像实例化对象,其实只是根据已有函数生成新的函数对象,并通过new关键字将this绑定到新创建的对象的调用上下文环境中。比如,var test =new foo(),用 new 来 调用 foo(..) 时,我们会构造一个新对象并把它绑定到foo(..) 调用中的 this 上。
  6. 箭头函数本身没有this,它在执行时会捕获调用所在词法作用域父函数的this。捕获绑定之后无法再次被修改。()=>的this是和词法作用域有关系的。而function定义的函数是和词法作用域没有关系的,只和调用环境有关系。http://stackoverflow.com/questions/35813344/do-es6-arrow-functions-still-close-over-this-even-if-they-dont-use-it
  7. this和JS中的Class可以关联使用,通过this的重新绑定可以实现混入 '父类'属相和方法的功能,也就实现了隐士的类似Class的伪多态。
根据下面这四条规则来判断this的绑定对象。
  1. 由 new 调用? 绑 定 到 新 创建 的 对象。
  2. 由 call 或者 apply( 或者 bind) 调用? 绑 定 到 指定 的 对象。
  3. 由上下文对象调用? 绑定到那个下文对象。
  4. 默认: 在严格模式下绑定到undefined,否则 绑 定 到 全局 对象。

二、何谓对象

  1. 从数据结构的角度来看,对象就是键/ 值对的集合。不论是String、Number、Function还是Array、JSON,它们构成对象后都是键/值对的集合。
  2. 函数就是对象的 一个 子 类型( 从 技术 角度 来说 就是“ 可调 用的 对象”)。
  3. 对象和变量一样作为二进制编码存储。
  4. 对象的内容是由 一些 存储 在特定命名位置 的( 任意 类型 的) 值 组成 的, 我们 称之为属性。对象存储在内存中,组成它的属性存储在其它位置。
  5. 直接声明的字符串类型是字面量类型。只是引擎会自动将字面量转化为 String对象。
  6. 对象的每个属性都有属性描述符“writable( 可 写)、 enumerable( 可 枚举) 和 configurable( 可 配置)”等。实际上'.属性名'这样的操作是触发了Get操作。
getter/setter:用来自定义对象属性的取值和赋值操作,会覆盖掉对象默认的[[Get]]和[[PUT]]算法。
  • 不论直接访问函数,还是通过属性访问函数,都是访问的函数引用。
  • 遍历对象属性的每个迭代器都可以接收一个回调函数,这个回调函数会应用到对象的每个属性上。forEach会遍历数组中的每一个元素。every会一直遍历直到回调函数返回false,some会一直遍历直到回调函数返回true。for...of...,直接遍历对象的属性或者数组的值,而不是遍历数组下标。

三、Class的本质

  1. 首先特别注意,JS没有类(对象的抽象模式/蓝图),只有对象,因此继承只能通过原型链来实现。JS中只有对象,可以粗俗的理解为所有的一切都是对象,它是真正面向对象。new关键词的作用就是将新产生的对象的原型链指向定义的函数对象本身。继承的含义是其它语言的复制机制,而在JS中不存在真正的继承机制,而是关联机制。在JS中是创建两个对象的关联。constructor并不是构造,只是指向了一个函数,把自己要做的事情委托给了自己原型链上关联的对象的方法。
  2. 类/ 继承描述 了一种代码的组织结构形式—— 一种 在 软件 中 对 真实 世界 中 问题 领域 的 建模 方法。面向 对象 编程 强调 的 是 数据 和 操作 数据 的 行为 本质上 是 互相 关联 的( 当然, 不同 的 数据 有 不同 的 行为), 因此 好的 设计 就是 把 数据 以及 和 它 相关 的 行为 打包( 或者说 封装) 起来。“类"也是一种设计模式,设计思想。面向 对象 设计 模式, 比如 迭代 器 模式、 观察者 模式、 工厂 模式、 单例模式。 建筑师提前设计好房屋,但是不关心建在哪里和建造多少个。建筑 和 蓝图 之间 的 关系 是 间接 的。 你 可以 通过 蓝图 了解 建筑 的 结构, 只 观察 建筑 本身 是 无法 获得 这些 信息 的。 但是 如果 你想 打开 一 扇 门, 那就 必须 接触 真实 的 建筑 才行—— 蓝图 只能 表示 门 应该 在哪, 但 并不是 真正 的 门。一个 类 就是 一张 蓝图。 为了 获得 真正 可以 交互 的 对象, 我们 必须 按照 类 来 建造( 也 可以说 实例 化) 一个 东西,这个东西就是对象,所以对象就是 类 中 描述 的 所有 特性 的 一份 副本。JS中的类的继承和实例化并不会发生复制行为,所以它不是真正的类。它不会创建副本,而只是对象之间被关联起来了。
  3. 标准面向对象语言中构造函数是属于类的,而在JS中类是属于构造函数的。JS中父类和子类的关系只存在于构造函数对应的.prototype中,所以构造函数只是一个委托关系函数,不能生成对象的副本。继承:实质上复制父类的副本,不会改变父类的方法,但在JS中不是这样的。所以说JS中是伪多态,js本身不提供多重继承机制。JS中的类继承是通过mixin或者prototype来实现的。
  4. 每一个JS对象都有一个内置的Prototype属性,它保存了对其它对象的引用。所有普通的原型链的尽头都是Object.prototype,它有很多通用的功能。对函数原型链的修改有时候会产生隐形属性屏蔽,并没有修改到原型链上。ES6的Class是显示伪多态的语法糖,是通过原型链来实现的,原型链委托的一种语法糖。
  5. 因为JS的原型链机制,所以JS可以使用两种设计思想,面向对象和委托关联(不同于.Net中的委托,不要误解)。
  6. 面向对象:是通过new来调用对象函数,并把新生成的对象的行为封装在new 调用对象中。 对象关联(委托):根据父对象创建子对象对齐的关联,然后逐步调用父对象的中的方法。
  7. 这是两种设计思想。Class只是把动态语法降低难度写上去像静态语法,虽然书写难度降低了,但是对理解底部真是的引擎运行机制形成了误导。委托调用的设计思想比面向对象的设计思想更加接近JS的真实运行机制。
super不像this是动态绑定的。因为动态绑定开销很大,它是在声明时静态绑定的。

转发自::http://www.cnblogs.com/ssol/

你不知道的This和Class的更多相关文章

  1. MySQL 系列(三)你不知道的 视图、触发器、存储过程、函数、事务、索引、语句

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...

  2. MySQL 系列(二) 你不知道的数据库操作

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 本章内容: 查看\创建\使用\删除 数据库 用户管理及授权实战 局域网 ...

  3. 《你不知道的JavaScript》整理(二)——this

    最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,这次研究了一下“this”. 当一个函数被调用时,会创建一个活动记录(执行上下文). 这个记录会包含函 ...

  4. 《你不知道的JavaScript》整理(一)——作用域、提升与闭包

    最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,里面分析了很多基础性的概念. 可以更全面深入的理解JavaScript深层面的知识点. 一.函数作用域 ...

  5. 你不知道的Javascript(上卷)读书笔记之一 ---- 作用域

    你不知道的Javascript(上卷)这本书在我看来是一本还不错的书籍,这本书用比较简洁的语言来描述Js的那些"坑",在这里写一些博客记录一下笔记以便消化吸收. 1 编译原理 在此 ...

  6. [No00002E]关于大数据,你不知道的6个迷思

    还是那个观点:计算机,编程语言,互联网,大数据等等都只是工具! 导语:看过美剧<纸牌屋>没?知道这部"白宫甄嬛传"为什么会火吗?靠的是大!数!据! 过去两年,在 Net ...

  7. 开源 VS 商业,消息中间件你不知道的那些事

    11月23日,新炬网络中间件技术专家刘拓老师在DBA+社群中间件用户组进行了一次主题为“开源 VS 商业,消息中间件你不知道的那些事”的线上分享.小编特别整理出其中精华内容,供大家学习交流. 嘉宾简介 ...

  8. 另5个你不知道的HTML5接口API

    原文地址: 5 More HTML5 APIs You Didn’t Know Existed 演示地址: 全屏API Demo 原文日期: 2012年11月08日 翻译日期: 2013年08月13日 ...

  9. 屌炸天实战 MySQL 系列教程(二) 史上最屌、你不知道的数据库操作

    此篇写MySQL中最基础,也是最重要的操作! 第一篇:屌炸天实战 MySQL 系列教程(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:屌炸天实战 MySQL 系列教程(二) 史上最屌.你不 ...

  10. 你不知道的JavaScript上卷笔记

    你不知道的JavaScript上卷笔记 前言 You don't know JavaScript是github上一个系列文章   初看到这一标题的时候,感觉怎么老外也搞标题党,用这种冲突性比较强的题目 ...

随机推荐

  1. linux tomcat 配置

    http://www.cnblogs.com/xdp-gacl/p/4097608.html

  2. ADIv5.2

    ADI:ARM Debug Interface,出到现在共有五代: 1)version1 and version 2:只针对ARM7TDMI和ARM9的processor: 2)version 3:只 ...

  3. zw版【转发·台湾nvp系列Delphi例程】HALCON Cast 使用方式

    zw版[转发·台湾nvp系列Delphi例程]HALCON Cast 使用方式 procedure TForm1.Button1Click(Sender: TObject);var img, img1 ...

  4. php setcookie 讲解

    1.setcookie 中 $value 值不能为数组 e.g a.$arr = array('hh','bb');setcookie('username',$arr);这种不会生效的 如果确实要放数 ...

  5. Java汉诺塔算法

    汉诺塔问题[又称河内塔]是印度的一个古老的传说. 据传开天辟地之神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把 ...

  6. 身为运维工程师怎么用Nginx部署DokuWiki

    运维人员按区域组织,人员分散,集中培训成本比较高: 新入职运维人员除了培训手册,没有其它渠道可以持续深入了解公司产品: 运维人员的知识存在各自脑袋里,缺少有效的渠道来传播和分享: 运维知识体系需要积累 ...

  7. JavaEE基础(十七)/集合

    1.集合框架(HashSet存储字符串并遍历) A:Set集合概述及特点 通过API查看即可 B:案例演示 HashSet存储字符串并遍历 HashSet<String> hs = new ...

  8. DomainHelper

    public class DomainHelper { public static void SetDomainValue(string key, object password) { AppDoma ...

  9. 使用crontab不能正常执行的问题

    crontab -l:   列出当前用户的crontab列表crontab -e:   以vi打开crontab文件,可以进行编辑.如果需要加新的自启动项目,可以在此进行添加后再输入:wq 保存. & ...

  10. http协议了解

    在web应用中,服务器把网页的HTML代码发送给浏览器,让浏览器显示出来,浏览器和服务器之间的传输协议就是HTTP协议.HTTP是在网络上传输HTML的协议,用于浏览器和服务器之间的通信. 一个网页打 ...