为什么String表现得像Array? -JS

时间:2019-05-30 06:41:24

标签: javascript arrays string types

我们都知道Strings的行为类似于Array。您甚至可以对其应用一些数组方法并从中受益,例如以下示例。

[].filter.call('abcdef',function(val){
    return val<'e';
});

var a='xyz';

我可以使用a[0]访问第一个元素,也可以像a.length一样调用Array

我的问题是,为什么String表现得像Array。如果是,为什么在检查false的实例时为何在下面得到Array。是String Array-like吗?

'a' instanceof Array

2 个答案:

答案 0 :(得分:5)

Array.prototype.filter真正需要做的就是,要迭代的变量具有length属性,并且该变量具有数字索引值。参见polyfill(的一部分):

var len = this.length >>> 0,
    res = new Array(len), // preallocate array
    t = this, c = 0, i = -1;
if (thisArg === undefined){
  while (++i !== len){
    // checks to see if the key was set
    if (i in this){
      if (func(t[i], i, t)){
        res[c++] = t[i];
      }
    }
  }
}

字符串满足此条件-字符串具有length属性,并且在字符串上访问的数字标记解析为单个字符。

但是您可以对任意对象执行相同的操作:

const obj = {
  0: 'foo',
  1: 'bar',
  length: 2
};

const result = [].filter.call(obj, val => val.startsWith('f'));
console.log(result);

您可以说obj也类似于数组,因为它具有length属性和数字标记。大多数.filter.reduce等数组方法都可以在类似数组的对象上.call使用,即使这些对象不是实际的数组。

(从技术上讲,您也可以在非类似数组的对象上调用数组方法,它只会做任何有用的事情-不能执行任何迭代)

答案 1 :(得分:1)

要使用instanceof,您需要创建一个Object的实例,而a不是一个实例。它是原始的,也称为string literal

  

String literals(用双引号或单引号表示)和字符串   在非构造函数上下文中从String调用返回(即,不包含   使用新关键字)原始字符串。自动JavaScript   将原语转换为String objects,以便可以使用   String object methods用于原始字符串。在以下情况下   方法是在原始字符串或属性查找上调用的   发生这种情况时,JavaScript会自动包装原始字符串和   调用该方法或执行属性查找。

例如:

let foo = 'abc'         // primitive
let boo = new String()  // object

console.log(foo instanceof String)  // false
console.log(boo instanceof String)  // true

console.log(typeof foo)  // 'string' <-- notice not String
console.log(typeof boo)  // object

这仅仅是由于:

  

instanceof运算符用于测试 constructor.prototype   对象的原型链

但是如上所述,我们正在处理的字符串文字是在没有构造函数调用的情况下创建的( new关键字),仅出于方便起见而被装箱。它们不是String的实际实例,因此instanceof返回false

您可以在字符串基元上使用Array.filter的原因仅仅是因为它是为您装箱到String所在的length属性的事实执行。

例如,在V8 engine字符串基元被解析/装箱到String,而StringStringObject的情况下。请注意,它们实际上是不同的实例。

Array.filter只关心该长度属性和CertainPerformance所指出的numeric indicies,这些属性由String的拳击框提供。示例:

console.log(Object.getOwnPropertyNames('a'))  // ["0", "length"]

但是String不是StringObject,因此instanceof将返回false