「Learning」JavaScript中原型和原型链深入理解

学习内容:JavaScript中原型和原型链深入理解

Learning Card

  • 辅助概念
    • 函数
    • 函数对象
    • 本地对象
    • 内置对象
    • 宿主对象
  • 原型和原型链
    • prototype
    • __proto__

笔记

辅助概念

函数

  • 类型
    • 函数声明
    • 函数表达式
  • 共同点
    • typeof检测结果都是function

upload successful

函数对象

函数就是对象,代表函数的对象就是函数对象

  • 语法上,每一个函数实际上都是一个函数对象

  • 用法上,通过函数来实例化出对象来使用

  • 在面向对象的范畴里,函数对象类似于的概念

本地对象(native object)

独立于宿主环境的ECMAScript实现提供的对象

包括:Object, Function, Array, String, Boolean, Number, Date, RegExp, Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError

  • 本地对象就是类(引用类型)
  • 使用typeof检测结果都是function

内置对象

由ECMAScript实现提供的、独立于宿主环境的所有对象,在ECMAScript程序开始执行时出现。

  • 开发者不必明确实例化内置对象,它已经被实例化了
  • 包含GlobalMath
  • 每个内置对象都是本地对象

原型和原型链

prototype

  • prototype是每一个函数都有的属性,但不是每一个对象都有的属性
  • 用于把共享的属性放到父类的实例中去(一改皆改)

__proto__

  • __proto__是每一个对象函数都隐含的属性
  • 它指向创建它的构造函数的prototype
  • 原型链就是通过这个属性构建的

我的理解:

  • 父类的prototype属性用来保存所有实例需要共享的属性和方法
  • 实例用__proto__属性来继承父类原型上的属性和方法

最核心的就是要记住一个公式

Father.prototype = Son.__proto__

这可以说是原型链第一大定律了!!!

我们可以通过一个例子来巩固这个知识点。

我们已知有AB两个构造函数,Aprototype是另一个函数对象B构造出的实例,我们可以尝试把它们连接起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function A() {...};
function B() {...};

var b = new B();
//A的prototype是B的实例,即
A.prototype = b;
var a = new A();
//最基本的关系如下
console.log(A.prototype === a.__proto__); //true
console.log(B.prototype === b.__proto__); //true
//延展关系如下
console.log(b === a.__proto__); //true
console.log(b.__proto__ === a.__proto__.__proto__); //true
console.log(B.prototype === a.__proto__.__proto__); //true
console.log(b.__proto__ === a.__proto__.__proto__); //true
//A和B都是Object构建出的实例
console.log(Object.prototype === A.__proto__);
console.log(Object.prototype === B.__proto__);
//可以看出实例a和Object的关系
//B.prototype === b.__proto__ => B.prototype.__proto__ === b.__proto__.__proto__ === a.__proto__.__proto__.__proto__ === Object.prototype
console.log(Object.prototype === a.__proto__.__proto__); //true
  • JS中万物皆对象,函数也是一种对象
  • JS中的所有东西都由Object衍生而来,所有东西的原型链的重点都指向Object.prototype
  • JS对象都由一个隐藏的__proto__属性,指向创建它的构造函数的原型;有一个例外是Object.prototype.__proto__指向null

FunctionObject的原型关系

  • 构造函数是通过Function构造出来的,Function也是通过Function构造出来的,所以**Function.prototype === Function.__proto__**
  • Object也是通过Function构造出来的,所以**Object.__proto__ === Function.prototype**
  • Function.prototype也是对象,也可以通过Object创建出来,所以,**Function.prototype.__proto__ ===Object.prototype**

关系备忘:

  • Father.prototype === Son.__proto__

  • Grandgrand...father.__proto__ === Object.prototype

  • Object.prototype.__proto__ === null

  • Function.prototype === Function.__proto__

  • Function.prototype ===Object.__proto__

  • Function.__proto__ === Object.__proto__

  • Function.prototype.__proto__ === Object.prototype