目录

1. 基本概念(关键词 知识点)§

  • 内存(图)、变量、数据类型、对象;

2. 控制语句§

  • if..else...
  • for...

3. 对象§

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

4. 难点§

  • 原型
  • this
  • AJAX

5. 最重要的知识§

5.1 JS公式§

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

JS唯一公式,直接套公式

5.2 根公理Object.prototype§

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

语言设计之初即规定好的

5.3 函数公理§

  • 所有函数都是由Function构造的
  • 任何函数.__proto__ === Function.prototype
  • 任意函数包括有Object / Array / Function

基于这三个知识和基础知识,可以推出JS世界

6. 常见错误观点 §

6.1 XXX的原型 §

  • {name:‘Frank’}
  • [1,2,3]
  • Object

当一问到“它们的原型分别是什么?”

  • 即是在问:“它们的.__proto__是什么?”
  • 而不是在问:“它们的.prototype是什么?”

正确的概念

  • 「的原型」等价于「.proto
  • 中文「原型」无法区分.__proto__.prototype
  • 约定:原型默认指.__proto__
  • 只不过.__proto__ 正好等于某个函数的一个属性,叫.prototype

6.2 所有对象的原型 §

矛盾点

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

正确的概念

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

6.3 对根对象Object.prototype的质疑 §

Object.prototype不是根对象(JS公理2 说是根对象)

似是而非的推论:

  • Object.prototype是所有对象的原型(√)
  • ObjectFunction构造出来的(√)
  • Function构造了Object.prototype(√)
  • Function看起来更像根对象(×)

正确的概念

  • Object.prototypeObject.prototype 对象 的区别
  • 地址 和 对象的区别
  • 对象里面从来不会包含另一个对象
  • 对象里面只包含另一个对象对应的地址 Object.prototype = #xxx 地址

    1
    
    typeof Object.prototype // "object" 不能判断
    
  • 依据内存图,假设Object.prototype指向一块内存#202

  • Object.prototypeObject里面吗?(不在)

  • Object.prototype指向#202是一个地址

  • #202是在内存中的对象

  • Object.prototype只表示地址,地址在Object里面

  • Object.prototype地址所对应的对象不在Object里面

  • Function构造了Object.prototype的地址,假设为#303

  • Function并未构造#303本身,即未构造根对象本身

  • Function构造了一个存根对象地址的属性,叫Object.prototype

7. JS世界的构造顺序 §

  1. 创建根对象 #101(包含 toString : .. 、valueOf : .. 、proto: null) 根对象没有名字
  2. 创建函数的原型 #208(包含 call 、apply 、proto: #101) 没有名字
  3. 创建数组的原型 #404(包含 push 、 pop 、 proto: #101) 没有名字
  4. 创建没有名字的Function #342(包含 Function.prototype: #208)
  5. Function.prototype等于 #208 (有地址名字了)
  6. 此时发现 Function__proto__Function都是 #208 (由浏览器指定 Function.__proto__ === Function.prototype
  7. Function创建 Object (实际没有名字) Object.__proto__ === Function.prototype #208
  8. Object.prototype等于 #101 (有地址名字了)
  9. Function创建 Array (实际没有名字) Array.__proto__ === Function.prototype #208
  10. Array.prototype等于 #404 (有地址名字了)
  11. 创建window对象(不属于JS世界)
  12. windowObjectArray属性将4 7 和 9 中的函数命名window.Function指向#2020 window.Object指向#707 window.Array指向#909 这三个对象有名字后 根才有名字
  13. 记住一点,JS创建一个对象时,不会给这个对象名字

过程分析

  • 1 2 3 创造原型
  • 4 构造一个构造出函数的函数 Function 关联 Function.prototype
  • 5 让函数的原型是(创建的)函数的原型
  • 6 让函数构造出的 函数的原型 也是(创建的)函数的原型
  • 看起来好像是 Function 自己构造了自己,但实际只是地址相同
  • 7 用 Function 构造 Object Object._proto__ === Function.prototype
  • 8 Object 构造出来的对象的原型(Object自己去构造对象时 用的公有属性 #101 挂在 Object.prototype上)
  • 9 用 Function 构造 Array Array._proto__ === Function.prototype
  • 10 Array 构造出来的对象的原型(Array自己去构造对象时 用的公有属性 #404 挂在 Array.prototype上)
  • 11 之前 都是假想的名字 没有实际的名字 创建 window 之后 将它们命名为 Function Object Array后 才有名字 它们的prototype才有名字

8. JS世界的构造顺序(续)§

8.1 new一个构造函数§

  • new Object()创建 obj1
  • new会将obj1的原型__proto__设置为Object.prototype (假设)并指向 #101(Object地址 根的地址)
  • new Array()创建 arr1
  • new会将arr1的原型__proto__设置为Array.prototype (假设)并指向 #404(Array的地址)
  • new Function()创建 fn1
  • new会将fn1的原型__proto__设置为Function.prototype (假设)并指向 #208(Function的地址)

new Xxx()一个x 就把 x.__proto__设置为Xxx.prototype

8.2 自定义构造函数§

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

9. 简要的图示§

举例说明三个圆形、三个函数和三个对象的关系

  • 三个函数:Array函数 Object函数 Function函数
  • 三个原型:数组的原型 对象的原型 函数的原型
  • 一一对应
  • Object函数的prototype存储了 根(对象的原型)
  • Function函数的prototype存储了 函数的原型
  • Array函数的prototype存储了 数组的原型
  • 即 每个函数 都存储了它自己的原型
  • 每个构造函数 存储了它自己的 对象的原型
  • 三个函数本身的原型(__proto__)是 函数的原型(#306)
  • 数组是对象,函数时对象
  • 函数的构造函数构造出了函数
  • 数组的构造函数构造出了数组
  • 对象的构造函数构造出了对象

10. 总结§

只能问 某物的原型是什么,单向性的问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
typeof Object.prototype // "object"
// 公理二 Object.prototype 是所有对象的原型
Object.prototype.__proto__ === null

typeof Function.prototype // "function"
Function.prototype.__proto__ === Object.prototype
// Function.prototype 的构造函数

const f = () => {}
f.__proto__ === Function.prototype

Function.__proto__ === Function.prototype

typeof Array.prototype.toString // "function"
Array.prototype.toString.__proto__ === Function.prototype

Object.__proto__ === Function.prototype

Array.prototype === [].__proto__

Array.__proto__ === Object.prototype

10.1 构造函数§

  • 是用来构造对象的
  • 会预先存好对象的原型,原型的原型是根
  • new的时候讲对象的__proto__对象原型

10.2 对象§

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

10.3 思考§

  • 如果加了这一环后,想再加一环
  • 要用到「继承」

11. 之后学的§

  • 错误处理try...catch.../Math/Date/正则/JSON
  • 网道
  • 项目中深入理解

·未完待续·

参考文章

相关文章