• 先来分析数组简单方法这一块

builtins-array.cc文件

  • 首先这个文件使用了如下几个文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
#include "src/code-factory.h"
#include "src/contexts.h"
#include "src/counters.h"
#include "src/debug/debug.h"
#include "src/elements-inl.h"
#include "src/global-handles.h"
#include "src/isolate.h"
#include "src/lookup.h"
#include "src/objects-inl.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/smi.h"
#include "src/prototype.h"
  • 我们多看看就会发现,实现Js数组方法的编写也是有规律的,由于面向对象的编程思想,首先我们要知道如下几点,:
    • 在这个文件中,方法实现的具体代码,是在BUILTIN(方法名)这边能看到。
    • 仔细查看源码,我们就会发现,在BUILTIN(方法名)之前,总会有namespace{},而namespace{}里面构造的函数,就是给为构造array方法而使用的,而namespace{}中的函数在C++有特定的名称,叫做内联函数
    • 再仔细查看这些内联函数实现的源代码,我们就会发现,内联函数的实现又要使用到,我们引用头文件中的其他命名空间中的函数
    • 这样层层封装虽然能提高开发效率,但是对初学者感觉不是很友好QAQ。(但是如果不封装的话,实现一个方法的代码量又非常多)

相关的内联函数

  • IsJSArrayFastElementMovingAllowed:判断是否允许对 JSArray 类型的对象进行“快速元素移动”

  • HasSimpleElements:用于检查一个 JSObject 对象是否具有“简单元素”。

  • HasOnlySimpleReceiverElements:用于判断某个对象是否仅具有简单的接收器元素

  • HasOnlySimpleElements:检查一个 JSObject 是否具有“简单元素”。

  • MatchArrayElementsKindToArguments:将数组的元素类型与参数匹配。

  • EnsureJSArrayWithWritableFastElements:确保一个 JSArray 对象拥有可写的快速元素(即能够高效地访问和修改数组元素)。

  • GetRelativeIndex:计算给定索引相对于某个基准索引的偏移量。

  • GetLengthProperty:获取数组或对象的 length 属性。

  • SetLengthProperty:设置数组或对象的 length 属性。

  • GenericArrayFill:用指定的值填充数组的元素。

  • TryFastArrayFill:尝试使用更快的方式填充数组。

封装完上面这些内联函数,就实现了ArrayPrototypeFill这个方法,这个方法的作用就是用于填充数组会指定的值。

1
2
3
let arr = [1, 2, 3, 4, 5];
arr.fill(0, 2, 4); // 将数组从索引 2 到索引 4 之间的元素替换为 0
console.log(arr); // 输出:[1, 2, 0, 0, 5]
  • GenericArrayPush:这个就是ArrayPush实现的核心内联函数

封装完GenericArrayPush函数,加上之前的内联函数,又可以实现一个ArrayPush的方法,这个放就是将指定值加入到数组的最后一个元素中

1
2
3
4
5
let arr = [1, 2, 3];

// 将元素添加到数组末尾
arr.push(4); // arr = [1, 2, 3, 4]
console.log(arr); // 输出: [1, 2, 3, 4]
  • GenericArrayPop:这个就是ArrayPop实现的核心内联函数