我们都知道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
答案 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,而String
到StringObject的情况下。请注意,它们实际上是不同的实例。
Array.filter
只关心该长度属性和CertainPerformance所指出的numeric indicies
,这些属性由String
的拳击框提供。示例:
console.log(Object.getOwnPropertyNames('a')) // ["0", "length"]
但是String
不是StringObject
,因此instanceof
将返回false
。