聊聊 Array 中的坑
栏目: JavaScript · 发布时间: 7年前
内容简介:原文:翻译:疯狂的技术宅本文首发微信公众号:jingchengyideng
原文: https://jakearchibald.com/201...
翻译:疯狂的技术宅
本文首发微信公众号:jingchengyideng
欢迎关注,每天都给你推送新鲜的前端技术文章
Array 类型检测
function foo(obj) {
// …
}
假设 obj
是一个数组,我们想要实现一些功能。比如 JSON.stringify
就是一个例子,它以不同的方式把数组输出到其他对象。
我们可以这样做:
if (obj.constructor == Array) // …
但是对于数组的子类来说这是错误的:
class SpecialArray extends Array {}
const specialArray = new SpecialArray();
console.log(specialArray.constructor === Array); // false
console.log(specialArray.constructor === SpecialArray); // true
所以如果你想检查子类的类型,那么应该用 instanceof
:
console.log(specialArray instanceof Array); // true console.log(specialArray instanceof SpecialArray); // true
但是当引入多个realm时,事情将会变得更加复杂:
Multiple realms
realm包含 self
引用的JavaScript全局对象。 因此,可以说在worker中运行的代码与在页面中运行的代码处于不同的realm。 在iframe之间也是如此,但同源iframe也共享一个ECMAScript'代理',这意味着对象可以 穿越 realm
。
接着看代码:
<iframe srcdoc="<script>var arr = [];</script>"></iframe>
<script>
const iframe = document.querySelector('iframe');
const arr = iframe.contentWindow.arr;
console.log(arr.constructor === Array); // false
console.log(arr.constructor instanceof Array); // false
</script>
这两个都是false,因为:
console.log(Array === iframe.contentWindow.Array); // false
iframe有自己的数组构造函数,它与父页面中的构造函数不同。
Array.isArray
console.log(Array.isArray(arr)); // true
Array.isArray
将为数组返回true,即使它们是在另一个realm中创建的。 对于任何realm的 Array
的子类,它也会返回true。 这就是 JSON.stringify
内部的处理方法。
但是,这并不意味着 arr
有 array 方法。 有些甚至所有方法都已设置为undefined,或者数组可能已将其整个原型删除:
const noProtoArray = []; Object.setPrototypeOf(noProtoArray, null); console.log(noProtoArray.map); // undefined console.log(noProtoArray instanceof Array); // false console.log(Array.isArray(noProtoArray)); // true
不管怎样,如果要杜绝上述问题,可以通过Array原型调用Array的方法:
if (Array.isArray(noProtoArray)) {
const mappedArray = Array.prototype.map.call(noProtoArray, callback);
// …
}
Symbols 与 realms
再看看这个:
<iframe srcdoc="<script>var arr = [1, 2, 3];</script>"></iframe>
<script>
const iframe = document.querySelector('iframe');
const arr = iframe.contentWindow.arr;
for (const item of arr) {
console.log(item);
}
</script>
上面的logs 1, 2, 3 很不引人注目,但 for-of 循环通过调用 arr[Symbol.iterator]
来工作,这在某种程度上可以跨越realm。 这是如何做:
const iframe = document.querySelector('iframe');
const iframeWindow = iframe.contentWindow;
console.log(Symbol === iframeWindow.Symbol); // false
console.log(Symbol.iterator === iframeWindow.Symbol.iterator); // true
虽然每个realm都有自己的Symbol实例,但Symbol.iterator在各个realm都是相同的。
Symbols同时也是JavaScript中最独特和最独特的东西。
The most unique 多唯一性
const symbolOne = Symbol('foo');
const symbolTwo = Symbol('foo');
console.log(symbolOne === symbolTwo); // false
const obj = {};
obj[symbolOne] = 'hello';
console.log(obj[symbolTwo]); // undefined
console.log(obj[symbolOne]); // 'hello'
传递给 Symbol
函数的字符串只是一个描述。 即使在同一realm内,这些Symbol也是独一无二的。
The least unique 最小唯一性
const symbolOne = Symbol.for('foo');
const symbolTwo = Symbol.for('foo');
console.log(symbolOne === symbolTwo); // true
const obj = {};
obj[symbolOne] = 'hello';
console.log(obj[symbolTwo]); // 'hello'
Symbol.for(str)
创建一个与传递它的字符串唯一的symbol。 有趣的是它在各个realms都是一样的:
const iframe = document.querySelector('iframe');
const iframeWindow = iframe.contentWindow;
console.log(Symbol.for('foo') === iframeWindow.Symbol.for('foo')); // true
这就是 Symbol.iterator
大致的工作原理。
创建自己的 'is' 函数
如果我们想要创建我们自己的“is”函数并跨越realm会怎么样? 好吧,Symbol允许我们这样做:
const typeSymbol = Symbol.for('whatever-type-symbol');
class Whatever {
static isWhatever(obj) {
return obj && Boolean(obj[typeSymbol]);
}
constructor() {
this[typeSymbol] = true;
}
}
const whatever = new Whatever();
Whatever.isWhatever(whatever); // true
即使实例来自另一个realm,即使它是一个子类,即使它的原型已被删除,也是可以的。
唯一的问题是,你需要确认自己的symbol名称在所有代码中都是唯一的。 如果其他人创建了他们自己的 Symbol.for('whatever-type-symbol')
并使用它来表示别的东西,那么 isWhatever
肯定返回false。
本文首发微信公众号:jingchengyideng
欢迎关注,每天都给你推送新鲜的前端技术文章
以上所述就是小编给大家介绍的《聊聊 Array 中的坑》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Building Social Web Applications
Gavin Bell / O'Reilly Media / 2009-10-1 / USD 34.99
Building a social web application that attracts and retains regular visitors, and gets them to interact, isn't easy to do. This book walks you through the tough questions you'll face if you're to crea......一起来看看 《Building Social Web Applications》 这本书的介绍吧!