JS总结

知识点

基本概念

内存、变量、数据类型、对象

控制语句

  • if…else…
  • for…

对象

  • 原型、原型链
  • 对象分类
  • new一个新对象
  • 构造函数
  • this的隐式传递和显式传递

难点

JS三座大山

  • 原型
  • this
  • AJAX

最重要的知识

JS公式

对象.__proto__===其构造函数.prototype

JS唯一公式,如果不会就套公式

根公理

Object.prototype是所有对象的(直接或间接)原型

加了一个直接或间接,所谓公理就是规定好的

函数公理

所有函数都是由Function构造的

任何函数.__proto__===Function.prototype

任意函数有Object/Array/Function

拨乱反正

乱一

XXX的原型

  • {name:'frank'}的原型

Object.prototype

  • [1, 2, 3]的原型

Array.prototype

  • Object的原型

Function.prototype

解读

  • Object的原型是Object.__proto__

  • Object的原型是Object.prototype

错在哪

  • 的原型等价于.__proto__
  • 中文的原型无法区分__proto__prototype
  • 所以我们只能约定,原型默认表示__proto__
  • 只不过__proto__正好等于某个函数的prototype

乱二

我觉得你矛盾了

  • [1, 2, 3]的原型是Array.prototype
  • 你又说Object.prototype是所有对象的原型
  • 那为什么Object.prototype不是[1, 2, 3]的原型

其实Array.prototypeObject.prototype都是[1, 2, 3]的原型。只不过一个是直接原型,一个是间接原型。

错在哪

  • 原型分为两种: 直接原型和间接原型
  • 对于普通对象来说,Object.prototype是直接原型
  • 对于数组、函数来说,Object.prototype是间接原型

乱三

Object.prototype不是根对象

理由

  • Object.prototype是所有对象的原型
  • ObjectFunction构造出来的
  • 所以,Function构造了Object.prototype

其实是Function构造了存Object.prototype(根对象)地址的这么一个属性,它并没有构造这个对象

  • 推论,Function才是万物之源呀

错在哪

  • Object.prototype(的地址)和Object.prototype对象的区别
  • 对象里面从来都不会包含另一个对象(它只会包含另一个对象的地址)

再画JS世界

上一版的JS世界: 内存图和 JS 世界

JS世界的构造顺序

  1. 创建根对象#101(toString),根对象没有名字
  2. 创建函数的原型#208(call/appy),原型__proto__#101
  3. 创建数组的原型#404(push/pop),原型__proto__#101
  4. 创建Function#342,原型__proto__#208
  5. 让Function.prototype等于#208(有名字了)
  6. (此时发现Function的__proto__prototype都是#208)
  7. 用Function创建Object(实际没有名字)
  8. 让Object.prototype等于#101(有名字了)
  9. 用Function创建Array(实际没有名字)
  10. 让Array.prototype等于#404(有名字了)
  11. 创建window对象(不属于JS世界)
  12. 用window的'Object'``’Array’属性将7和9中的函数命名
  13. 记住一点,JS创建一个对象时,不会给这个对象名字的

JS世界的构造顺序(续)

如果要有一个新的对象,要做什么事情呢?

  1. new Object()创建obj1
  2. new会将obj1的原型__proto__设置为Object.prototype,也就是#101

Q: 为什么要设置为Object.prototype

A: 因为我们在创建JS世界的时候,把原型的地址存在了这个上面

  1. new Array()创建arr1
  2. new会将arr1的原型__p设置为Array.prototype,也就是#404
  3. new Function创建f1
  4. new会将f1的原型__proto__设置为Function.prototype,也就是#208

new什么,就把这个对象的原型设置成 什么的prototype.

JS世界的构造顺序(续)

  1. 自己定义构造函数Person,函数里给this加属性
  2. Person自动创建prototype属性和对应的对象#502
  3. 在Person.prototype#502上面加属性
  4. new Person()创建对象p
  5. new会将p的原型__proto__设为#502

漂亮的图示

Object函数的prototype存储了根,就是对象的原型这么一个对象

每个函数存储了自己的原型,每个构造函数存储了它自己的对象的原型。

你品,你细品,你再自己好好细品。

总结

构造函数

  • 是用来构造对象的

函数的构造函数构造出了函数,数组的构造函数构造出了数组,对象的构造函数构造出了对象

  • 会预先存好对象的原型,原型的原型是根
  • new的时候将对象的__proto__指向原型

对象

  • 所有对象都直接或间接指向根对象
  • 如果对象想要分类,就在原型链上加一环
  • 用构造对象可以加这一环

JS三大定理

结合JS三大定理来回答一下下面的这些问题

问题

  • Object.prototype的原型?

Object.prototype.__proto__ === null

  • Function.prototype的原型?

Function.prototype.__proto__ === Object.prototype

  • var f = ()=> {}的原型?

f.__proto__ = Function.prototype

  • Function的原型?

Function.__proto__ === Function.prototype

  • Array.prototype.toString的原型?

Array.prototype.toString.__proto__ === Function.prototype

  • Object的原型?

Object.__proto__=== Function.prototype

  • Array.prototype是什么东西的原型?

Array.prototype === [].__proto__

comments powered by Disqus