For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/proposal-array-last.md.
  • 简体中文
  • Getting last element of Array ?

    中文标题:获取数组的最后一个元素

    提案概览
    提案速览

    该提案解决了通过 array\[array.length - 1\] 获取数组最后一个元素这一常见但容易出错的模式。它提议在 Array.prototype 上添加两个新属性:作为 getter/setter 的 lastItem 和作为 getter 的 lastIndex,并采用通用算法,也适用于类数组对象。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    从数组中获取最后一项

    (目前处于 Stage 1)

    该提案的推动者(@keithamus)目前不计划推进到 Stage 2。其他提案(Array.prototype.itemArray Slice Notation)也充分解决了这个问题,并且在标准轨道上推进得更快。如果其中一个提案推进到 Stage 3,本提案将被放弃。

    理由

    目前获取数组最后一个元素的唯一方法是从 .length 属性减去 1,并使用该值进行属性查找。通常写法为 someArray[someArray.length - 1]

    对于如此常见的操作,很容易忘记从 length 属性中减去 -1,或者过度使用,因此应该有更简单的语法来做这件事。

    myArray[myArray.length] // 哎呀,索引越界,返回 `undefined`,因愚蠢错误而挠头数小时
    
    
    myIndex = myArray.length - 1
    myArray[myIndex - 1] // 哎呀,索引过度,返回倒数第二个而非最后一个,因愚蠢错误而挠头数小时

    高层提案

    Array.prototype.lastItem 是一个具有 getter/setter 函数的属性,返回数组的最后一项。 Array.prototype.lastIndex 是一个具有 getter 函数的属性,返回数组的最后一个索引。

    规范

    22.1.3.xx Array.prototype.lastItem
    
    这是一个属性,其属性为 { [[Enumerable]]: false, [[Configurable]]: false, [[Get]]: GetLastArrayItem, [[Set]]: SetLastArrayItem }。
    
    22.1.3.xx GetLastArrayItem 
    
    调用 GetLastArrayItem 方法时,执行以下步骤:
    
        让 O 为 ? ToObject(this 值)。
        让 len 为 ? ToLength(? Get(O, "length"))。
        如果 len 为零,则
            返回 undefined。
        否则 len > 0,
            将 len 设为 len-1。
            让 index 为 ! ToString(len)。
            让 element 为 ? Get(O, index)。
            返回 element。 
    
    GetLastArrayItem 函数有意保持通用性;它不要求其 this 值必须是 Array 对象。因此它可以被转移到其他类型的对象上作为方法使用。
    
    22.1.3.xx SetLastArrayItem (value)
    
    调用 SetLastArrayItem 方法时,执行以下步骤:
    
        让 O 为 ? ToObject(this 值)。
        让 len 为 ? ToLength(? Get(O, "length"))。
        如果 len > 0,则
            将 len 设为 len-1。
        让 index 为 ! ToString(len)。
        返回 ? Set(O, index, value)。
    
    注意 1
    
    SetLastArrayItem 函数有意保持通用性;它不要求其 this 值必须是 Array 对象。因此它可以被转移到其他类型的对象上作为方法使用。
    
    22.1.3.xx Array.prototype.lastIndex
    
    这是一个属性,其属性为 { [[Enumerable]]: false, [[Configurable]]: false, [[Get]]: GetLastArrayIndex }。
    
    22.1.3.xx GetLastArrayIndex 
    
    调用 GetLastArrayIndex 方法时,执行以下步骤:
    
        让 O 为 ? ToObject(this 值)。
        让 len 为 ? ToLength(? Get(O, "length"))。
        如果 len > 0,则
            返回 len-1。
        返回 0。
    
    注意 1
    
    The GetLastArrayIndex 函数有意保持通用性;它不要求其 this 值必须是 Array 对象。因此它可以被转移到其他类型的对象上作为方法使用。

    Polyfill

    Polyfill 可在 core-js 库中找到。你可以在 ECMAScript 提案部分 找到它。

    这是一个使用抽象 ECMAScript 操作的 polyfill:

    import { ToString, ToObject, ToLength } from 'es-abstract'
    // 这个 polyfill 尽可能贴近规范。有些 polyfill 可以用更少的代码。
    Object.defineProperty(Array.prototype, 'lastItem', {
      enumerable: false,
      configurable: false,
      get() {
        let O = ToObject(this)
        let len = ToLength(O.length)
        if (len === 0) {
          return undefined
        } else if (len > 0) {
          len = len -1
          let index = ToString(len)
          let element = O[index]
          return element
        }
      },
      set(value) {
        let O = ToObject(this)
        let len = ToLength(O.length)
        if (len > 0) {
          len = len -1
        }
        let index = ToString(len)
        return O[index] = value
      },
    })
    Object.defineProperty(Array.prototype, 'lastIndex', {
      enumerable: false,
      configurable: false,
      get() {
        let O = ToObject(this)
        let len = ToLength(O.length)
        if (len > 0) {
          return len - 1
        }
        return 0
      },
    })
    其他考虑过的选项
    • Array.prototype.last/Array.prototype.last() 最初被提议,但存在 Web 兼容性问题。
    • Array.prototype.end() 作为方法。缺点仍然是用笨拙的语法设置数组的最后一个元素。
    • Array.prototype.end 作为 getter。然而 lastItem 是更受欢迎的名称选择。
    • Array.prototype.peek() 被考虑过(与 pushpop 配合良好),但 peek 作为 setter 不直观。
    • Array.prototype.prePop() 被提到,但存在与 peek 相同的问题——对于设置不直观,而且如果它不改变原数组,可能令人惊讶。
    • 一堆其他名称。最重要的是,请参见以下命名标准的理由:
      • 没有 Web 兼容性问题
      • 属于最常见的 1000 个英语单词(last 和 end 都是)
      • 对于获取和设置都应该直观
      • 理想情况下不是复合词(比如 lastItem)