gpt4 book ai didi

javascript - Javascript集合

转载 作者:行者123 更新时间:2023-12-02 10:14:09 25 4
gpt4 key购买 nike

很抱歉出现noobie问题。您能否解释一下,两者之间有什么区别?

1. var a = [];
a['b'] = 1;

2. var a = {};
a['b'] = 1;


我在网上找不到在这里写的文章。

最佳答案

文字

[]{}分别称为数组和对象文字。

var x = []var x = new Array();的缩写

var y = {}var y = new Object();的缩写

数组

数组是具有length属性的结构。您可以通过其数字索引访问值。

var x = [] or var x = new Array();
x[0] = 'b';
x[1] = 'c';


如果要列出所有属性,请执行以下操作:

for(var i = 0; i < x.length; i++)
console.log(x[i]);// numeric index based access.


性能技巧和陷阱

1.内部缓存length属性

标准数组迭代:

for (var i = 0; i < arr.length; i++) {
// do stuff
};


鲜为人知的事实:在上述情况下, arr.length属性在for循环的每个步骤中都被读取。就像您在此处调用的任何函数一样:

for (var i = 0; i < getStopIndex(); i++) {
// do stuff
};


这无缘无故地降低了性能。内部缓存进行救援:

for (var i = 0, len = arr.length; i < len; i++) {
// enter code here
};


Here's以上证明。

2.不要在构造函数中指定Array的长度。

// doing this:
var a = new Array(100);
// is very pointless in JS. It will result in an array with 100 undefined values.

// not even this:
var a = new Array();
// is the best way.

var a = [];
// using the array literal is the fastest and easiest way to do things.


here提供了用于数组定义的测试用例。

3.避免使用Array.prototype.push(arr.push)

如果要处理大型集合,则直接分配比使用 Array.prototype.push();方法要快。

根据jsPerf.com test casesmyArray[i] = 0;myArray.push(0);更快。

4.将数组用于关联分配是错误的。

它起作用的唯一原因是因为 Array在JS语言的核心内部扩展了 Object类。例如,您也可以使用 Date();RegEx();对象。不会有什么不同。
x['property'] = someValue必须始终与对象一起使用。

数组应仅具有数字索引。请参阅 THIS,Google JS开发指南!避免 for (x in arr)循环或 arr['key'] = 5;

可以很容易地进行备份,以 HERE为例。

var x = [];
console.log(x.prototype.toString.call);


将输出: [object Array]

这揭示了核心语言的“类”继承模式。

var x = new String();
console.log(x.prototype.toString.call);


将输出 [object String]

5.从数组中获取最小值和最大值。

鲜为人知但功能强大的技巧:

function arrayMax(arr) {
return Math.max.apply(Math, arr);
};


, 分别:

function arrayMin(arr) {
return Math.min.apply(Math, arr);
};


对象

使用对象只能执行以下操作:

var y = {}var y = new Object();

y['first'] = 'firstValue'y.first = 'firstValue'相同,您不能使用数组。对象设计用于通过 String键进行关联访问。

迭代是这样的:

for (var property in y) {
if (y.hasOwnProperty(property)) {
console.log(y.property);
};
};


性能技巧和陷阱

1.检查对象是否具有属性。

大多数人使用 Object.prototype.hasOwnProperty。不幸的是,这常常会导致错误的结果,从而导致意外的错误。

这是一个好方法:

function containsKey(obj, key) {
return typeof obj[key] !== 'undefined';
};


2.替换switch语句。

简单而有效的JS技巧之一就是 switch替换。

switch (someVar) {
case 'a':
doSomething();
break;
case 'b':
doSomethingElse();
break;
default:
doMagic();
break;
};


在大多数JS引擎中,上述过程非常缓慢。当您查看三种可能的结果时,并没有什么不同,但是如果您有几十个或几百个呢?

上面的内容很容易替换为一个对象。不要添加结尾的 (),这不是执行函数,而只是存储对它们的引用:

var cases = {
'a': doSomething,
'b': doSomethingElse,
'c': doMagic
};


代替 switch

var x = ???;
if (containsKey(cases, x)) {
cases[x]();
} else {
console.log("I don't know what to do!");
};


3.轻松进行深克隆。

function cloneObject(obj) {
var tmp = {};
for (var key in obj) {
tmp[key] = fastDeepClone(obj[key];
};
return tmp;
}

function cloneArr(arr) {
var tmp = [];
for (var i = 0, len = arr.length; i < len; i++) {
tmp[i] = fastDeepClone(arr[i]);
}
return tmp;
}


function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
};

function isArray(obj) {
return obj instanceof Array;
}

function isObject(obj) {
var type = typeof obj;
return type === 'object' && obj !== null || type === 'function';
}

function fastDeepClone(obj) {
if (isArray(obj)) {
return cloneArr(obj);
} else if (isObject(obj)) {
return cloneObject(obj);
} else {
return obj;
};
};


HERE是起作用的深度克隆功能。

自动装箱

作为一种动态类型化的语言,JavaScript受本机对象类型的限制:


目的
数组

布尔型
日期
正则表达式
错误



Null不是类型, typeof null是对象。


有什么收获?原始对象与非原始对象之间有很大的区别。

var s = "str";
var s2 = new String("str");


它们执行相同的操作,您可以在 ss2上调用所有字符串方法。
然而:

type of s == "string"; // raw data type
type of s2 == "object" // auto-boxed to non-primitive wrapper type
s2.prototype.toString.call == "[object String]";


您可能会在JS中听到所有内容都是 object。尽管确实很容易犯错,但这并不完全正确。

实际上,有两种类型,基元和对象,当您调用 s.indexOf("c")时,JS引擎将自动将 s转换为其非原始包装类型,在这种情况下为 object String,其中所有方法都在 String.prototype

这称为 auto-boxingObject.prototype.valueOf(obj)方法是一种强制从原始类型强制转换为非原始类型的方法。这与Java之类的语言针对其自身的许多原语引入的行为相同,特别是对: int-整数, double-Double, float-浮点等。

你为什么要在乎呢?

简单:

function isString(obj) {
return typeof obj === "string";
}
isString(s); // true
isString(s2); // false


因此,如果使用 s2创建了 var s2 = new String("test"),即使对于原本可以想到的简单类型检查,也会得到假阴性。更复杂的对象也会带来沉重的性能损失。

有人会说这是微优化,但结果确实是惊人的,即使对于字符串初始化之类的非常简单的事情也是如此。让我们在性能方面比较以下两个:

var s1 = "this_is_a_test" 




var s2 = new String("this_is_a_test")


您可能会期望获得全面的匹配性能,但是令人惊讶的是,如前所述,使用 new String的后一条语句要比第一个慢92%。

功能

1.默认参数

||运算符是最简单的默认方式。为什么行得通?因为诚实和虚假的价值观。

在逻辑条件下进行评估时, undefinednull值将自动广播到 false

一个简单的例子(代码 here):

function test(x) {
var param = x || 5;
// do stuff with x
};


2. OO JS

要了解的最重要的事情是JavaScript this对象不是不可变的。它只是一个可以轻松更改的参考。

在OO JS中,我们依靠 new关键字来保证JS类的所有成员中的隐式作用域。即使这样,您也可以通过 Function.prototype.callFunction.prototype.apply轻松更改范围。

另一个非常重要的事情是 Object.prototype。嵌套在对象原型上的非原始值可以共享,而原始值则不能共享。

带有示例 HERE的代码。

一个简单的类定义:

function Size(width, height) {
this.width = width;
this.height = height;
};


一个简单的大小类,具有两个成员 this.widththis.height

在类定义中,任何前面带有 this的东西都会为Size的每个实例创建一个新引用。

向类添加方法以及“ closure”模式和其他“ fancy name pattern”为什么是纯小说

这也许是发现最恶意的JavaScript反模式的地方。

我们可以通过两种方式在 Size类中添加方法。

Size.prototype.area = function() {
return this.width * this.height;
};


要么:

function Size2(width, height) {
this.width = width;
this.height = height;
this.area = function() {
return this.width * this.height;
}
}

var s = new Size(5, 10);
var s2 = new Size2(5, 10);



var s3 = new Size2(5, 10);
var s4 = new Size(5, 10);
// Looks identical, but lets use the reference equality operator to test things:
s2.area === s3.area // false
s.area === s4.area // true


为每个实例创建 areaSize2方法。
这是完全没用的,而且很慢,很多都比较慢。确切地说是89%。看 HERE

上面的声明对所有已知的“花式名称模式”的大约99%有效。记住JS中最重要的一件事情,所有这些不过是虚构而已。

可以提出强有力的体系结构论证,主要围绕数据封装和闭包的使用。

不幸的是,这些东西在JavaScript中绝对是一文不值的,性能损失根本不值得。我们谈论的是90%及以上,这几乎可以忽略不计。

3.局限性

因为 prototype定义在类的所有实例之间共享,所以您将不能在其中放置非基本设置对象。

Size.prototype.settings = {};


为什么?每个实例的 size.settings都相同。
那么,原语是什么?

Size.prototype.x = 5; // won't be shared, because it's a primitive.
// see auto-boxing above for primitive vs non-primitive
// if you come from the Java world, it's the same as int and Integer.


要点:

一般的JS家伙会通过以下方式编写JS:

var x = {
doStuff: function(x) {
},
doMoreStuff: 5,
someConstant: 10
}


只要您了解这是一个 Singleton对象,就可以了(好的=质量差,代码难以维护),并且这些函数只能在全局范围内使用,而不能在其中引用 this

但是随后它变成了绝对糟糕的代码:

var x = {
width: 10,
height: 5
}
var y = {
width: 15,
height: 10
}


您可能已经摆脱了: var x = new Size(10, 5); var y = new Size(15, 5);

输入需要更长的时间,您每次都需要输入相同的内容。再说一遍,它慢很多。看 HERE

整个标准差

这几乎可以在任何地方看到:

   function() {
// some computation
var x = 10 / 2;
var y = 5;
return {
width: x,
height: y
}
}


再次使用替代方法:

function() {
var x = 10 / 2;
var y = 5;
return new Size(10, 5);
};


重点:只要合适就使用类!

为什么?示例1是93%慢速。看 HERE
这里的示例很简单,但是它们说明了JS,OO中忽略的某些内容。

不雇用那些认为JS没有课程的人,也不要从谈论“面向对象” JS的招聘人员那里获得工作,这是一个可靠的经验法则。

关闭

许多人都喜欢上面的方法,因为它给了他们数据封装的感觉。除了大幅降低90%的性能外,这同样容易被忽略。内存泄漏。

function Thing(someParam) {
this.someFn = function() {
return someParam;
}
}


您刚刚为 someParam创建了一个闭包。为什么这样不好?首先,它迫使您将类方法定义为实例属性,从而导致性能大幅下降。

其次,它会消耗内存,因为闭包永远不会被取消引用。查找 HERE作为证明。当然,您确实得到了一些虚假的数据封装,但是使用的内存是内存的三倍,性能下降了90%。

或者,您可以添加 @private并获得带下划线功能名称的方法。

生成闭包的其他非常常见的方式:

function bindSomething(param) {
someDomElement.addEventListener("click", function() {
if (param) //do something
else // do something else
}, false);
}


param现在关闭了!您如何摆脱它?有各种技巧,有些可以找到 here。尽管更为严格,但最好的方法是避免一起使用匿名函数,但这将需要一种方法来指定事件回调的作用域。

据我所知,这种机制仅在Google Closure中可用。

单例模式

好,那我要为单身人士做什么?我不想存储随机引用。这是一个很好的主意,从 here

/**
* Adds a {@code getInstance} static method that always return the same instance
* object.
* @param {!Function} ctor The constructor for the class to add the static
* method to.
*/
function addSingletonGetter(ctor) {
ctor.getInstance = function() {
if (ctor.instance_) {
return ctor.instance_;
}
return ctor.instance_ = new ctor;
};
};


它具有Java风格,但这是一个简单而强大的技巧。您现在可以执行以下操作:

project.some.namespace.StateManager = function() {
this.x_ = 5;
};
project.some.namespace.prototype.getX = function() { return x; }
addSingletonGetter(project.some.namespace.StateManager);


这有什么用?简单。在所有其他文件中,每次需要引用 project.some.namespace.StateManager时,都可以编写:
project.some.namespace.StateManager.getInstance()。这比看起来更棒。

您可以拥有类定义(继承,有状态成员等)的好处而具有全局状态,而不会污染全局名称空间。

单实例模式

您现在可能很想这样做:

function Thing() {
this.someMethod = function() {..}
}
// and then use it like this:
Thing.someMethod();


这是JavaScript中的另一大禁忌。请记住,只有在使用 this关键字时,才能保证 new对象是不可变的。上面代码背后的魔力很有趣。 this实际上是全局范围,因此对您没有意义的是将方法添加到全局对象。您猜对了,那些东西永远都不会被垃圾收集。

没有任何内容告诉JavaScript使用其他东西。 function本身没有作用域。务必小心使用 static属性。为了重现我曾经阅读过的报价,JavaScript全局对象就像一个公共厕所。有时,您别无选择,只能去那里,但要尽量减少与表面的接触。

坚持上述 Singleton模式,或使用嵌套在名称空间下的设置对象。

JavaScript中的垃圾回收

JavaScript是一种垃圾回收语言,但是对JavaScript GC的了解却很少。关键再次是速度。这也许太熟悉了。

// This is the top of a JavaScript file.
var a = 5;
var b = 20;
var x = {};//blabla

// more code
function someFn() {..}


那是不好的,性能不好的代码。原因很简单。 JS只会垃圾收集一个变量并释放该变量所拥有的堆内存,只有当该变量被解除作用域时,例如在内存中的任何地方都没有引用它。

例如:

function test(someArgs) {
var someMoreStuf = // a very big complex object;
}
test();


三件事:


函数参数被转换为局部定义
内部声明为 Google Closure's base.js
函数完成执行后,将释放分配给内部变量的所有堆内存。


为什么?
因为它们不再属于“当前”范围。它们是创建,使用和销毁的。也没有闭包,因此通过垃圾回收释放了您已使用的所有内存。

出于这个原因,您永远都不要,您的JS文件也永远不要这样,因为全局作用域只会污染内存。

var x = 5;
var y = {..}; //etc;


好吧,现在呢?

命名空间。

JS的每个名称空间都没有,因此这并不是Java的等效名称,但是从代码库管理的角度来看,您可以得到想要的东西。

var myProject = {};
myProject.settings = {};
myProject.controllers = {};
myProject.controlls.MainController = function() {
// some class definition here
}


美丽。一个全局变量。正确的项目结构。
在构建阶段,您可以将项目拆分为多个文件,并获得合适的开发环境。

从这里可以实现的目标是无限的。

计算您的图书馆

享受了无数代码库的乐趣之后,最后一个也是最重要的参数是要牢记您的代码依赖性。我见过程序员随意将jQuery添加到堆栈的混合中以获得简单的动画效果,等等。

在创建Bower之类的工具之前,JavaScript世界一直以来都没有解决依赖关系和程序包管理问题。浏览器仍然有些慢,即使速度很快,互联网连接也很慢。

例如,在Google的世界中,他们花费大量时间编写整个编译器只是为了节省字节,这种方法在许多方面都是Web编程中应有的正确思路。我高度赞赏Google,因为他们的JS库为Google Maps这样的应用程序提供了强大的动力,这些应用程序不仅异常复杂,而且可以在任何地方使用。

可以说,JavaScript具有广泛的可用工具,因为它的受欢迎程度,可访问性以及在某种程度上来说非常低的质量使整个生态系统都愿意接受。

对于Hacker News订阅者而言,没有新的JS库就不会一天过去了,它们当然是有用的,但是不能忽略这样一个事实,即其中许多人重新实现了完全相同的关注而没有任何新奇的观念或任何新的观念。杀手的想法和改进。

在所有新玩具有时间证明它们对整个生态系统的新颖性和实用性以及强烈区分周日编码的乐趣和生产部署之前,抵制在所有新玩具中混合的冲动是一个很强的经验法则。

如果您的 <head></head>标记比这篇文章长,则说明您做错了。

测试您的JavaScript知识

一些“完美主义者”级别的测试:


hoisted,感谢Kangax。
http://perfectionkills.com/javascript-quiz/

关于javascript - Javascript集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12973706/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com