一条快速获取 Javascript 真相的途径

489 阅读4分钟

这是一篇方法论的文章,鉴于笔者水平有限,难免会有纰漏。但是实在想分享一种“授人以渔”的方法。因为最近看了一些面试题,大多数都在零零碎碎的写各种总结和技巧。总得来说,会有收获,每个作者的分享也很不错。然而凡事总怕但是——但是,我这里要说的是,这些经验式的总结和技巧,如同一个个芝麻粒一样,无序和零散。这就是我写这篇文章的目的,现在的媒介资源,让我可以轻而易举获得各种大小的芝麻粒,然而芝麻背后的道理?如何知晓?

Javascript 是什么

说起前端 Javascript,我们通常指的是客户端 ECMAScript 以及 BOM 和 DOM 的结合体。Javascript 还有其他环境中的变体在此不再赘述。本文也不讨论 BOM 和 DOM 的细节,它们都是一堆 API 的实现。直接呼应本文标题【一条获取 Javascript 真相的途径】,就在 ECMAScript 之中。ECMAScript 全称是:European Computer Manufacturers Association。这么长的单词,并不重要,我们只要知道它是一个标准化的脚本程序设计语言即可。

Object.create 探讨 ECMAScript 里有什么

这一段开始,就是我想认真探讨的问题。我们先来看一个实例:如何实现/模拟 Object.create

这里有一个实现,可以参考。可是,为什么是这样?这么写的来源又是在哪里?其实反过来思考,如果我们知道原理,下面的例子或许就不能称作一个问题,

Object.create = function (obj) {
    var B={};
    B.__proto__=obj;
    return B;
};

这原理,自然就在 ECMAScript 之中。在正片开始之前,重要的东西发三遍:

下图是以上链接的内容示例。

pic

这个文档非常好用,提供了定位当前链接,图钉和查看引用以及搜索的功能。我们可以通过直接输入 Object.create 定位到相关实现。伪代码如下:

19.1.2.2 Object.create ( O, Properties )

The create function creates a new object with a specified prototype. When the create function is called, the following steps are taken:

  1. If Type(O) is neither Object nor Null, throw a TypeError exception.
  2. Let obj be ObjectCreate(O).
  3. If Properties is not undefined, then
    1. Return ? ObjectDefineProperties(obj, Properties).
  4. Return obj.

通过以上定义得知,实现一个 Object.create 需要大致四步,我们来按照说明实现如下。这个 create 方法创建了一个拥有特殊原型的对象。当方法调用时,执行以下四步:

  1. 判断对象类型是否是对象或null,如果不是,抛出一个错误。
  2. 创建一个空对象(这里面还有一个抽象操作名为:ObjectCreate 用来定义运行时的普通对象)
  3. 如果第二个参数不是 undefined。那么返回 ObjectDefineProperties(obj, properties) 的调用结果(这一步也是由一个名为: ObjectDefinePropertis 的抽象操作完成的。它的主要作用就是返回一个包含第二个参数属性的对象,这些属性跟 Object.defineProperties(obj, props) 的第二个参数相对应)。
  4. 返回该对象

好了,针对以上论述我们应该能容易实现如下代码:

function myObjectCreate(obj, properties) {
  if (typeof obj !== "object") {
    throw new Error("not a object");
  }
  let tempObj = {}; //
  tempobj.__proto__ = obj;
  if (properties !== undefined) {
    Object.defineProperties(tempObj, properties);
  }
  return tempObj;
}

以上算是根据 ECMAScript 的标准实现了一遍 Object.create。过程比较简单,其中有两个抽象操作,我们如果不去阅读这份实现,在实际开发中永远不会遇到。但是,如果你对这深层次的实现有一定的了解或者认识,那么会在写代码的过程中带着更顺畅的理解去实现功能。这其中区别,不用多说了吧。

回顾

现在我们回头看看,这篇文章其实没有多少知识点。如同我开始所讲,希望前端开发者不要总是过着吃别人丢过来的鱼片过日子。当我们学会捕鱼(钓鱼不太合适)的时候,有很多东西,不言自明。如果针对本文中的例子有所体会,也一定是你自己要通过阅读 ECMAScript 的实现来完成。这份标准的词汇量很少,也没有晦涩的语法。坚持探究下去,里面还讲了 bind call apply 的定义。这些经常会在各种面试题中出现,如果你能理解这内部的操作过程以及逻辑,想必再也不用死记硬背这些枯燥乏味的实现了吧。我们回头看 Object.create 的实现:

  1. 判断类型
  2. 创建空对象并绑定 proto
  3. 处理属性描述符,如果存在的话
  4. 返回该对象

可是如果我们看最开始的那份答案:

Object.create = function (obj) {
    var B={};
    B.__proto__=obj;
    return B;
};

这里写的是很简单易懂,但也就止步到此了。希望本文能给你带来一些启发,我们共同进步,如果有什么建议,还望不吝赐教。

pic