Heim Web-Frontend js-Tutorial Array, Array Constructor, for in loop, typeof, instanceOf_javascript技巧

Array, Array Constructor, for in loop, typeof, instanceOf_javascript技巧

May 16, 2016 pm 06:02 PM
array constructor

注意: JavaScript 中数组不是 关联数组。 JavaScript 中只有对象 来管理键值的对应关系。但是关联数组是保持顺序的,而对象不是。

由于 for in 循环会枚举原型链上的所有属性,唯一过滤这些属性的方式是使用 `hasOwnProperty` 函数,因此会比普通的 for 循环慢上好多倍。

遍历(Iteration)
为了达到遍历数组的最佳性能,推荐使用经典的 for 循环。

复制代码 代码如下:

var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i console.log(list[i]);
}

上面代码有一个处理,就是通过 l = list.length 来缓存数组的长度。

虽然 length 是数组的一个属性,但是在每次循环中访问它还是有性能开销。 可能最新的 JavaScript 引擎在这点上做了优化,但是我们没法保证自己的代码是否运行在这些最近的引擎之上。

实际上,不使用缓存数组长度的方式比缓存版本要慢很多。

`length` 属性(The `length` property)
length 属性的 getter 方式会简单的返回数组的长度,而 setter 方式会截断数组。
复制代码 代码如下:

var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]

foo.length = 6;
foo; // [1, 2, 3]

译者注:在 Firebug 中查看此时 foo 的值是: [1, 2, 3, undefined, undefined, undefined] 但是这个结果并不准确,如果你在 Chrome 的控制台查看 foo 的结果,你会发现是这样的: [1, 2, 3] 因为在 JavaScript 中 undefined 是一个变量,注意是变量不是关键字,因此上面两个结果的意义是完全不相同的。

// 译者注:为了验证,我们来执行下面代码,看序号 5 是否存在于 foo 中。
5 in foo; // 不管在 Firebug 或者 Chrome 都返回 false
foo[5] = undefined;
5 in foo; // 不管在 Firebug 或者 Chrome 都返回 true
为 length 设置一个更小的值会截断数组,但是增大 length 属性值不会对数组产生影响。

结论(In conclusion)
为了更好的性能,推荐使用普通的 for 循环并缓存数组的 length 属性。使用 for in 遍历数组被认为是不好的代码习惯并倾向于产生错误和导致性能问题。

Array 构造函数
由于 Array 的构造函数在如何处理参数时有点模棱两可,因此总是推荐使用数组的字面语法 - [] - 来创建数组。

[1, 2, 3]; // 结果: [1, 2, 3]
new Array(1, 2, 3); // 结果: [1, 2, 3]

[3]; // 结果: [3]
new Array(3); // 结果: []
new Array('3') // 结果: ['3']
译者注:这里的模棱两可指的是数组的两种构造函数语法 var arr1 = new Array(arrayLength); var arr2 = new Array(element0, element1, ..., elementN);

// 译者注:因此下面的代码将会使人很迷惑
new Array(3, 4, 5); // 结果: [3, 4, 5]
new Array(3) // 结果: [],此数组长度为 3
由于只有一个参数传递到构造函数中(译者注:指的是 new Array(3); 这种调用方式),并且这个参数是数字,构造函数会返回一个 length 属性被设置为此参数的空数组。需要特别注意的是,此时只有 length 属性被设置,真正的数组并没有生成。译者注:在 Firebug 中,你会看到 [undefined, undefined, undefined],这其实是不对的。在上一节有详细的分析。

var arr = new Array(3);
arr[1]; // undefined
1 in arr; // false, 数组还没有生成
这种优先于设置数组长度属性的做法只在少数几种情况下有用,比如需要循环字符串,可以避免 for 循环的麻烦。

new Array(count + 1).join(stringToRepeat);
// 译者注:new Array(3).join('#') 将会返回 "##"
结论(In conclusion)
应该尽量避免使用数组构造函数创建新数组。推荐使用数组的字面语法。它们更加短小和简洁,因此增加了代码的可读性。

for in 循环
和 in 操作符一样,for in 循环同样在查找对象属性时遍历原型链上的所有属性。

注意: for in 循环不会遍历那些 enumerable 设置为 false 的属性;比如数组的 length 属性。
复制代码 代码如下:

// 修改 Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
console.log(i); // 输出两个属性:bar 和 moo
}

由于不可能改变 for in 自身的行为,因此有必要过滤出那些不希望出现在循环体中的属性,这可以通过 Object.prototype 原型上的 `hasOwnProperty` 函数来完成。

注意: 由于 for in 总是要遍历整个原型链,因此如果一个对象的继承层次太深的话会影响性能。

使用 `hasOwnProperty` 过滤(Using `hasOwnProperty` for filtering)
复制代码 代码如下:

// foo 变量是上例中的
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}

这个版本的代码是唯一正确的写法。由于我们使用了 hasOwnProperty,所以这次只输出 moo。如果不使用 hasOwnProperty,则这段代码在原生对象原型(比如 Object.prototype)被扩展时可能会出错。

一个广泛使用的类库 Prototype 就扩展了原生的 JavaScript 对象。因此,但这个类库被包含在页面中时,不使用 hasOwnProperty 过滤的 for in 循环难免会出问题。

最佳实践(Best practices)
推荐总是使用 hasOwnProperty。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。

typeof 操作符
typeof 操作符(和 `instanceof` 一起)或许是 JavaScript 中最大的设计缺陷,因为几乎不可能从它们那里得到想要的结果。

尽管 instanceof 还有一些极少数的应用场景,typeof 只有一个实际的应用(译者注:这个实际应用是用来检测一个对象是否已经定义或者是否已经赋值),而这个应用却不是用来检查对象的类型。

注意: 由于 typeof 也可以像函数的语法被调用,比如 typeof(obj),但这并是一个函数调用。那两个小括号只是用来计算一个表达式的值,这个返回值会作为 typeof 操作符的一个操作数。实际上不存在名为 typeof 的函数。

JavaScript 类型表格(The JavaScript type table)
Value Class Type
-------------------------------------
"foo" String string
new String("foo") String object
1.2 Number number
new Number(1.2) Number object
true Boolean boolean
new Boolean(true) Boolean object
new Date() Date object
new Error() Error object
[1,2,3] Array object
new Array(1, 2, 3) Array object
new Function("") Function function
/abc/g RegExp object (function in Nitro/V8)
new RegExp("meow") RegExp object (function in Nitro/V8)
{} Object object
new Object() Object object
上面表格中,Type 一列表示 typeof 操作符的运算结果。可以看到,这个值在大多数情况下都返回 "object"。

Class 一列表示对象的内部属性 [[Class]] 的值。

JavaScript 标准文档中定义: [[Class]] 的值只可能是下面字符串中的一个: Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String.

为了获取对象的 [[Class]],我们需要使用定义在 Object.prototype 上的方法 toString。

对象的类定义(The Class of an object)
JavaScript 标准文档只给出了一种获取 [[Class]] 值的方法,那就是使用 Object.prototype.toString。
复制代码 代码如下:

function is(type, obj) {
var clas = Object.prototype.toString.call(obj).slice(8, -1);
return obj !== undefined && obj !== null && clas === type;
}

is('String', 'test'); // true
is('String', new String('test')); // true

上面例子中,Object.prototype.toString 方法被调用,this 被设置为了需要获取 [[Class]] 值的对象。

译者注:Object.prototype.toString 返回一种标准格式字符串,所以上例可以通过 slice 截取指定位置的字符串,如下所示:
复制代码 代码如下:

Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(2) // "[object Number]"

ES5 提示: 在 ECMAScript 5 中,为了方便,对 null 和 undefined 调用 Object.prototype.toString 方法,其返回值由 Object 变成了 Null 和 Undefined。

译者注:这种变化可以从 IE8 和 Firefox 4 中看出区别,如下所示:
复制代码 代码如下:

// IE8
Object.prototype.toString.call(null) // "[object Object]"
Object.prototype.toString.call(undefined) // "[object Object]"

// Firefox 4
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
测试为定义变量(Testing for undefined variables)
typeof foo !== 'undefined'

上面代码会检测 foo 是否已经定义;如果没有定义而直接使用会导致 ReferenceError 的异常。这是 typeof 唯一有用的地方。

结论(In conclusion)
为了检测一个对象的类型,强烈推荐使用 Object.prototype.toString 方法;因为这是唯一一个可依赖的方式。正如上面表格所示,typeof 的一些返回值在标准文档中并未定义,因此不同的引擎实现可能不同。

除非为了检测一个变量是否已经定义,我们应尽量避免使用 typeof 操作符。

instanceof 操作符
instanceof 操作符用来比较两个操作数的构造函数。只有在比较自定义的对象时才有意义。如果用来比较内置类型,将会和 typeof 操作符 一样用处不大。

比较自定义对象(Comparing custom objects)
复制代码 代码如下:

function Foo() {}
function Bar() {}
Bar.prototype = new Foo();

new Bar() instanceof Bar; // true
new Bar() instanceof Foo; // true

// 如果仅仅设置 Bar.prototype 为函数 Foo 本省,而不是 Foo 构造函数的一个实例
Bar.prototype = Foo;
new Bar() instanceof Foo; // false
`instanceof` 比较内置类型(Using `instanceof` with native types)
new String('foo') instanceof String; // true
new String('foo') instanceof Object; // true

'foo' instanceof String; // false
'foo' instanceof Object; // false

有一点需要注意,instanceof 用来比较属于不同 JavaScript 上下文的对象(比如,浏览器中不同的文档结构)时将会出错,因为它们的构造函数不会是同一个对象。

结论(In conclusion)
instanceof 操作符应该仅仅用来比较来自同一个 JavaScript 上下文的自定义对象。正如 `typeof` 操作符一样,任何其它的用法都应该是避免的。
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Array mit der Array.Sort-Funktion in C# sortieren Array mit der Array.Sort-Funktion in C# sortieren Nov 18, 2023 am 10:37 AM

Titel: Beispiel für die Verwendung der Array.Sort-Funktion zum Sortieren eines Arrays in C#. Text: In C# ist Array eine häufig verwendete Datenstruktur, und häufig sind Array-Sortiervorgänge erforderlich. C# stellt die Array-Klasse bereit, die über die Sort-Methode verfügt, um Arrays bequem zu sortieren. In diesem Artikel wird gezeigt, wie Sie ein Array mithilfe der Array.Sort-Funktion in C# sortieren, und es werden spezifische Codebeispiele bereitgestellt. Zunächst müssen wir die grundlegende Verwendung der Array.Sort-Funktion verstehen. Array.So

Einfache und klare Methode zur Verwendung der PHP-Funktion array_merge_recursive() Einfache und klare Methode zur Verwendung der PHP-Funktion array_merge_recursive() Jun 27, 2023 pm 01:48 PM

Beim Programmieren in PHP müssen wir häufig Arrays zusammenführen. PHP stellt die Funktion array_merge() bereit, um die Array-Zusammenführung abzuschließen. Wenn jedoch derselbe Schlüssel im Array vorhanden ist, überschreibt diese Funktion den ursprünglichen Wert. Um dieses Problem zu lösen, stellt PHP in der Sprache auch eine Funktion array_merge_recursive() bereit, die Arrays zusammenführen und die Werte derselben Schlüssel beibehalten kann, wodurch das Programmdesign flexibler wird. array_merge

So verwenden Sie die Funktion array_combine in PHP, um zwei Arrays zu einem assoziativen Array zu kombinieren So verwenden Sie die Funktion array_combine in PHP, um zwei Arrays zu einem assoziativen Array zu kombinieren Jun 26, 2023 pm 01:41 PM

In PHP gibt es viele leistungsstarke Array-Funktionen, die Array-Operationen komfortabler und schneller machen können. Wenn wir zwei Arrays zu einem assoziativen Array kombinieren müssen, können wir diese Operation mit der Funktion array_combine von PHP ausführen. Diese Funktion wird tatsächlich verwendet, um die Schlüssel eines Arrays als Werte eines anderen Arrays zu einem neuen assoziativen Array zu kombinieren. Als nächstes erklären wir, wie man die Funktion array_combine in PHP verwendet, um zwei Arrays zu einem assoziativen Array zu kombinieren. Erfahren Sie mehr über array_comb

Detaillierte Erläuterung der Verwendung der PHP-Funktion array_fill() Detaillierte Erläuterung der Verwendung der PHP-Funktion array_fill() Jun 27, 2023 am 08:42 AM

In der PHP-Programmierung ist Array eine sehr wichtige Datenstruktur, die große Datenmengen problemlos verarbeiten kann. PHP bietet viele Array-bezogene Funktionen, array_fill() ist eine davon. In diesem Artikel wird die Verwendung der Funktion array_fill() ausführlich vorgestellt und einige Tipps für praktische Anwendungen gegeben. 1. Übersicht über die Funktion array_fill() Die Funktion der Funktion array_fill() besteht darin, ein Array mit demselben Wert und einer angegebenen Länge zu erstellen. Konkret lautet die Syntax dieser Funktion

Wie kann der Konstruktor einer Klasse durch Constructor Property Promotion in PHP8 vereinfacht werden? Wie kann der Konstruktor einer Klasse durch Constructor Property Promotion in PHP8 vereinfacht werden? Oct 18, 2023 am 10:51 AM

Wie vereinfacht man den Konstruktor einer Klasse durch ConstructorPropertyPromotion in PHP8? In PHP8 wurde die Funktion ConstructorPropertyPromotion (Heraufstufung von Konstruktoreigenschaften) eingeführt, die das Schreiben von Klassenkonstruktoren prägnanter und effizienter macht. Diese Funktion kann redundanten Code reduzieren und die Lesbarkeit und Wartbarkeit des Codes verbessern. In diesem Artikel wird ConstructorPropertyPro ausführlich vorgestellt

Was sind die häufigsten Ursachen für ArrayIndexOutOfBoundsException in Java? Was sind die häufigsten Ursachen für ArrayIndexOutOfBoundsException in Java? Jun 24, 2023 pm 10:39 PM

Java ist eine sehr leistungsfähige Programmiersprache, die in verschiedenen Entwicklungsbereichen weit verbreitet ist. Bei der Java-Programmierung stoßen Entwickler jedoch häufig auf ArrayIndexOutOfBoundsException-Ausnahmen. Was sind also die häufigsten Ursachen dieser Anomalie? ArrayIndexOutOfBoundsException ist eine häufige Laufzeitausnahme in Java. Dies bedeutet, dass beim Zugriff auf Daten der Array-Index den Bereich des Arrays überschreitet. Häufige Gründe sind:

Einführung in die Verwendung der PHP-Funktion array_change_key_case() Einführung in die Verwendung der PHP-Funktion array_change_key_case() Jun 27, 2023 am 10:43 AM

In der PHP-Programmierung ist Array ein häufig verwendeter Datentyp. Es gibt auch eine ganze Reihe von Array-Operationsfunktionen, einschließlich der Funktion array_change_key_case(). Diese Funktion kann die Groß-/Kleinschreibung von Schlüsselnamen im Array umwandeln, um unsere Datenverarbeitung zu erleichtern. In diesem Artikel wird die Verwendung der Funktion array_change_key_case() in PHP vorgestellt. 1. Funktionssyntax und Parameter array_change_ke

Wie konvertiert man LinkedList in Java in ein Array? Wie konvertiert man LinkedList in Java in ein Array? Aug 29, 2023 pm 11:09 PM

Die toArray()-Methode der LinkedList-Klasse konvertiert das aktuelle LinkedList-Objekt in ein Array vom Objekttyp und gibt es zurück. Dieses Array enthält alle Elemente dieser Liste in der richtigen Reihenfolge (vom ersten bis zum letzten Element). Es fungiert als Brücke zwischen Array-basierten und Sammlungs-basierten APIs. Konvertieren Sie also LinkedList in ein Array und instanziieren Sie die LinkedList-Klasse. Füllen Sie es mit der Methode add(). Rufen Sie die Methode toArray() für die oben erstellte verknüpfte Liste auf und rufen Sie das Array von Objekten ab. Konvertiert jedes Element eines Arrays von Objekten in eine Zeichenfolge. Beispiel Echtzeitdemonstration von importjava.util.Arrays;importjava.uti

See all articles