深入明白JS中的工具(一)

目录

  • 一切皆是工具吗?
  • 工具
    • 原型与原型链
    • 组织函数
  • 参考

1.一切皆是工具吗?

首先,“在 JavaScript 中,一切皆是工具”这种表述是不完全准确的。

JavaScript 的数据类型分为两类:原始值类型和工具(Object类型)。

原始值类型(ES5):

  • undefined
  • null – typeof null 的值为”object”,是由于 ES5 规范划定:对于 null 值的 typeof 字符串值返回”object”
  • true/false – 布尔值
  • number
  • string
var a = undefined
var b = null
var c = true
var d = 1
var e = "abc"

这些值是在底层上直接实现的,他们不是object,以是没有原型(__proto__),没有组织函数(constructor)。

但我们再实践历程中,会发现虽然字符串,布尔值和数字是原始值类型,但却显示得有点像工具。

以字符串为例:

深入明白JS中的工具(一)

在上图中,可以看到界说了一个值为”abc”的字符串变量 e,接见其 _proto_ 和 constructor 属性,发现其居然有值?不是说原始值类型没有原型和组织函数,这是怎么回事呢?

原来原始值类型(布尔值、数字、字符串)有其对应的包装器工具:Boolean(布尔工具)、Number(数字工具)、String(字符串工具),在这些原始值类型上实验挪用属性或方式(好比 constructor 等)时,JS会自动举行 Auto-Boxing(暂且包装)的历程,首先将其转换为暂且包装器工具,再接见其上的属性或方式,而不会影响原始值类型的属性。

这也能解释为什么我们直接对原始值类型变量(布尔值、数字、字符串)添加了一些属性,再次接见依旧为 undefined,由于我们接见属性操作的是暂且包装器工具,不会影响基本原始值类型自己。如下图:

深入明白JS中的工具(一)

而原始值类型(null 与 undefined)没有对应的包装器工具,以是在其上实验接见任何属性或方式都市报错。如下图:

深入明白JS中的工具(一)

2.工具

在JS中,Object 是一个属性的聚集,而且拥有一个单独的原型工具 [prototype object] (其可以是一个 object 或 null 值)。

在浏览器或 Node.js 中,可以通过 _proto_ 属性接见这个原型工具, _proto_ 被称为该工具的原型,但为了和函数的原型属性(prototype)区分,一样平常称其为隐式原型。

var position = {
  x: 10,
  y: 20,
  z: 30,
}

上面的代码中,工具与隐式原型的关系如下图:

深入明白JS中的工具(一)

(1)原型与原型链

在JS中,工具的继续关系是通过隐式原型(__proto__)来实现的。工具的隐式原型在工具建立时由工具的组织函数自动关联,也可以通过修改隐式原型,更改工具的继续关系。

不要把异常当做营业逻辑,这性能可能你无法蒙受

由 Object 组织函数建立的工具,其隐式原型指向 Object.prototype。而 Object.prototype 工具的隐式原型的值默以为 nulll。

代码示例:

// x, y, z 的隐式原型 __proto__ 默认都指向 Object.prototype
var x = {
    a: 10,
}
var y = {
    a: 20,
    b: 30,
}
var z = {
    a: 40,
    b: 50,
    c: 60,
}
  
// 设置 x 的隐式原型为 y
// 设置 y 的隐式原型为 z
x.__proto__ = y
y.__proto__ = z
  
console.log(x.a)  // 10 - 来自 x 自身的属性
console.log(x.b)  // 30 - 来自 y 的属性
console.log(x.c)  // 60 - 来自 z 的属性

// 修改 y 的属性 b 的值
y.b = 70

console.log(x.b)  // 70 - 来自 y 的属性

// 移除 z 的属性 c
delete z.c

console.log(x.c)  // undefined - 沿着隐式原型一级一级往上找,没有找到该属性

从上述代码,我们可以看到,当接见一个工具的属性时,会优先在这个工具的属性中查找是否存在所要接见的属性,若存在,则获取乐成,住手查找;若没有找到该属性,则会继续去查找该工具的隐式原型中是否存在,若存在,则获取乐成,住手查找;若照样没有查找到,将继续再往上一级的隐式原型中查找,直到找到则返回找到的属性值 或 直到遇到隐式原型值为 null 则返回 undefined。

这种由原型相互关联(指向)的关系就形成了所谓的原型链,而工具的属性或方式的查找就是沿着原型链顺序举行查找的。

上述代码示例中的原型链关系如下图:

深入明白JS中的工具(一)

(2)组织函数

首先要明了,函数也是一个特殊的工具,除了和其他工具一样有 _proto_ 属性外,另有自己特有的属性——显示原型(prototype),这个属性指向一个工具,其用途就是包罗所有实例共享的属性和方式。显示原型工具也有一个 constructor 属性,这个属性指向原组织函数。

而所谓组织函数,就是提供一个天生工具的模板,并形貌工具的基本结构的函数。一个组织函数,可以天生多个工具,每个工具都有相同的结构。而JS中所有函数(除了箭头函数)都可以当做组织函数。

一个工具由组织函数建立时,其隐式原型(__proto__)指向组织该工具的组织函数(constructor)的显示原型(prototype),这保证了实例能够接见在组织函数原型中界说的属性和方式。

代码示例:

// 组织函数 C
function C(x) {
    this.x = x
}

// 继续属性 y
C.prototype.y = 30

// new 两个工具实例a、b
var a = new C(10)
var b = new C(20)

console.log(a.x) // 10
console.log(a.y) // 30
console.log(b.x) // 20
console.log(b.y) // 30

// 工具实例 a、b 的隐式原型(__proto__)指向组织该工具的组织函数 C 的显示原型(prototype)
console.log(a.__proto__ === C.prototype) // true
console.log(b.__proto__ === C.prototype) // true

// 组织函数的显示原型(prototype)的 constructor 属性指向原组织函数
console.log(C === C.prototype.constructor) // true

// 组织函数 C、Function 与 Object 的隐式原型(__proto__)指向组织该工具的组织函数 Function 的显示原型(prototype)
console.log(C.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true
console.log(Object.__proto__ === Function.prototype) // true

// C.prototype 与 Function.prototype 的隐式原型(__proto__)指向组织该工具的组织函数 Object 的显示原型(prototype)
console.log(C.prototype.__proto__ === Object.prototype) // true
console.log(Function.prototype.__proto__ === Object.prototype) // true

// Object.prototype 的隐式原型(__proto__)即是 null
console.log(Object.prototype.__proto__ === null) // true

上述代码示例中的完整原型链关系如下图:

深入明白JS中的工具(一)

从上图我们可以总结:

  1. 所有的(隐式)原型链的最末尾最终都市指向 null(JS不允许有循环原型链,制止死循环)

  2. 所有函数默认都是有 Function 组织函数建立,即所有函数的隐式原型(__proto__)都指向 Function.prototype。

  3. 所有工具默认都继续自Object工具,即默认情形下,所有工具的(隐式)原型链的末尾都指向 Object.prototype。

注:所谓默认情形,即没有手动修改原型链关系。

3.参考

JS中一切都是工具吗?看这一篇就知道了

js中__proto__和prototype的区别和关系?

深入明白JavaScript系列(10):JavaScript焦点(晋级妙手必读篇)

深入明白JavaScript系列(18):面向工具编程之ECMAScript实现(推荐)

原创文章,作者:2d28新闻网,如若转载,请注明出处:https://www.2d28.com/archives/8622.html