不再更新,已经有人维护中文版本,地址:https://github.com/loverajoel/jstips
新的一年,新的项目. 每天一个JS小技巧
《Introducing JavaScript Tips》 中文翻译版,原地址:https://github.com/loverajoel/jstips
With great excitement, I introduce these short and useful daily JavaScript tips that will allow you to improve your code writing. With less than 2 minutes each day, you will be able to read about performance, conventions, hacks, interview questions and all the items that the future of this awesome language holds for us.
怀着兴奋的心情,我将介绍一些简短有用的JavaScript日常小技巧,这可能会帮助你提高你的代码编写水平。伴随着每天不到两分钟的阅读,你将会了解JavaScript的性能、约定、Hacks、面试问题。
At midday, no matter if it is a weekend or a holiday, a tip will be posted and tweeted.
在每个午休时刻,无论是周末还是假期,这样的一条条JavaScript小技巧将会发布。
2016-01-15 by @jhogoforbroke
JavaScript by default does not have a contains method. And for checking existence of a substring in string or item in array you may do this:
var someText = 'javascript rules';
if (someText.indexOf('javascript') !== -1) {
}
// or
if (someText.indexOf('javascript') >= 0) {
}But let's look at these Expressjs code snippets.
for (var key in obj) {
// "reserved" exports
if (~['name', 'prefix', 'engine', 'before'].indexOf(key)) continue;exports.normalizeType = function(type){
return ~type.indexOf('/')
? acceptParams(type)
: { value: mime.lookup(type), params: {} };
};// key is invalid
if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key'));The gotcha is the bitwise operator ~, "Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values."
It transforms -1 into 0, and 0 is false in javascript, so:
var someText = 'text';
!!~someText.indexOf('tex'); //sometext contains text - true
!~someText.indexOf('tex'); //sometext not contains text - false
~someText.indexOf('asd'); //sometext contains asd - false
~someText.indexOf('ext'); //sometext contains ext - trueIn ES6 was introduced the includes() method and you can use to determine whether or not a string includes another string:
'something'.includes('thing'); // trueWith ECMAScript 2016 (ES7) is even possible uses with Arrays, like indexOf:
!!~[1, 2, 3].indexOf(1); // true
[1, 2, 3].includes(1); // trueUnfortunately, It's got support only in Chrome, Firefox, Safari 9 or above and Edge. Not IE11 or less.
It's better to using in controlled environments.
2016-01-13 by @pklinger
Introduced as a new feature in ES6, fat arrow functions may come as a handy tool to write more code in less lines. The name comes from its syntax as => is a 'fat arrow' compared to a thin arrow ->. Some programmers might already know this type of functions from different languages such as Haskell as 'lambda expressions' respectively 'anonymous functions'. It is called anonymous, as these arrow functions do not have a descriptive function name.
- Syntax: less LOC; no more typing
functionkeyword over and over again - Semantics: capturing the keyword
thisfrom the surrounding context
Have a look at these two code snippets, which exactly do the same job. You will quickly understand what fat arrow functions do.
// general syntax for fat arrow functions
param => expression
// may also be written with parentheses
// parentheses are required on multiple params
(param1 [, param2]) => expression
// using functions
var arr = [5,3,2,9,1];
var arrFunc = arr.map(function(x) {
return x * x;
});
console.log(arr)
// using fat arrow
var arr = [5,3,2,9,1];
var arrFunc = arr.map((x) => x*x);
console.log(arr)As you may see, the fat arrow function in this case may save you time typing out the parentheses as well as the function and return keywords. I would advice you to always write parentheses around the parameter inputs as the parentheses will be needed for multiple input parameters such as in (x,y) => x+y anyways. It is just a way to cope with forgetting them in different use cases. But the code above would also work like this: x => x*x. So far these are only syntactical improvements, which lead to less LOC and better readability.
There is another good reason to use fat arrow functions. There is the issue with the context of this. With arrow functions, you will not worry about .bind(this) or setting that = this anymore, as fat arrow functions pick the context of this from the lexical surrounding. Have a look at the next [example] (https://jsfiddle.net/pklinger/rw94oc11/):
// globally defined this.i
this.i = 100;
var counterA = new CounterA();
var counterB = new CounterB();
var counterC = new CounterC();
var counterD = new CounterD();
// bad example
function CounterA() {
// CounterA's `this` instance (!! gets ignored here)
this.i = 0;
setInterval(function () {
// `this` refers to global object, not to CounterA's `this`
// therefore starts counting with 100, not with 0 (local this.i)
this.i++;
document.getElementById("counterA").innerHTML = this.i;
}, 500);
}
// manually binding that = this
function CounterB() {
this.i = 0;
var that = this;
setInterval(function() {
that.i++;
document.getElementById("counterB").innerHTML = that.i;
}, 500);
}
// using .bind(this)
function CounterC() {
this.i = 0;
setInterval(function() {
this.i++;
document.getElementById("counterC").innerHTML = this.i;
}.bind(this), 500);
}
// fat arrow function
function CounterD() {
this.i = 0;
setInterval(() => {
this.i++;
document.getElementById("counterD").innerHTML = this.i;
}, 500);
}Further information about fat arrow functions may be found at [MDN] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). To see different syntax options visit [this site] (http://jsrocks.org/2014/10/arrow-functions-and-their-scope/).
2016-01-13 by @manmadareddy
For quickly measuring performance of a javascript block, we can use the console functions like
console.time(label) and console.timeEnd(label)
console.time("Array initialize");
var arr = new Array(100),
len = arr.length,
i;
for (i = 0; i < len; i++) {
arr[i] = new Object();
};
console.timeEnd("Array initialize"); // Outputs: Array initialize: 0.711msMore info:
Demo: jsfiddle - codepen (outputs in browser console)
2016-01-12 by Avraam Mavridis
In many programming languages the parameters of a function is by default mandatory and the developer has to explicitly define that a parameter is optional. In Javascript every parameter is optional, but we can enforce this behavior without messing the actual body of a function taking advantage of the [es6's default values for parameters] (http://exploringjs.com/es6/ch_parameter-handling.html#sec_parameter-default-values) feature.
在许多编程语言中,方法的参数是强制需要的,开发人员必须明确的定义一个可选的参数。在 JavaScript 中任何参数都是可选的,但是我们可以利用[ES6的默认参数值]特点的优势去实现强制要求这种表现而不污染本身函数体。
const _err = function( message ){
throw new Error( message );
}
const getSum = (a = _err('a is not defined'), b = _err('b is not defined')) => a + b
getSum( 10 ) // throws Error, b is not defined
getSum( undefined, 10 ) // throws Error, a is not defined
_erris a function that immediately throws an Error. If no value is passed for one of the parameters, the default value is gonna be used,_errwill be called and an Error will be throwed. You can see more examples for the default parameters feature on Mozilla's Developer Network
_err 是一个即使抛出错误的方法,如果参数中的任意一个没有值,默认的参数就会被使用,_err 将会被调用并且抛出一个错误。你可以在这里看到更多的例子
2016-01-11 by @squizzleflip
Understanding hoisting will help you organize your function scope. Just remember, variable declaration and function definition are hoisted to the top. Variable definition is not, even if you declare and define a variable on the same line. Also, variabledeclaration is letting the system know that the variable exists while definition is assigning it a value.
理解变量提升将会帮助你组织函数作用域问题。切记,变量声明和函数声明都会提升到顶部。即使你在同一行声明一个变量和定义一个变量,变量定义也不会提升。变量的声明是让系统知道存在这个变量,但是变量的赋值是指给这个变量赋一个值。
function doTheThing() { // ReferenceError: notDeclared is not defined
console.log(notDeclared);
// Outputs: undefined
console.log(definedLater);
var definedLater;
definedLater = 'I am defined!' // Outputs: 'I am defined!'
console.log(definedLater)
// Outputs: undefined
console.log(definedSimulateneously);
var definedSimulateneously = 'I am defined!' // Outputs: 'I am defined!'
console.log(definedSimulateneously)
// Outputs: 'I did it!' doSomethingElse();
function doSomethingElse(){ console.log('I did it!'); }
// TypeError: undefined is not a function functionVar();
var functionVar = function(){ console.log('I did it!'); }
}To make things easier to read, declare all of your variables at the top of your function scope so it is clear which scope the variables are coming from. Define your variables before you need to use them. Define your functions at the bottom of your scope to keep them out of your way.
为了保证你的代码更加容易阅读,请将所有的变量都声明在函数的顶端,这样的话可以更加清楚的知道变量来自于哪个作用域。在你需要使用变量之前定义他们。在作用域的最后定义函数方法。
2016-01-10 by @loverajoel
When you have to check if a property is present of an object, you probably are doing something like this:
当你要检查一个属性是否在一个对象里面的时候,你可能会这样做:
var myObject = {
name: '@tips_js'
};
if (myObject.name) { ... }Thats ok, but you have to know that there are two native ways for this kind of thing, the
inoperator andObject.hasOwnProperty, every object descended fromObject, has available both ways.
这样当然是没有问题的,但是你一定要知道这儿有两个原生的方法可以解决这个问题,那就是 in 和 hasOwnProperty ,任何继承与 object 的对象都能使用这两个方法。
var myObject = {
name: '@tips_js'
};
myObject.hasOwnProperty('name'); // true
'name' in myObject; // true
myObject.hasOwnProperty('valueOf'); // false, valueOf is inherited from the prototype chain
'valueOf' in myObject; // trueBoth differs in the depth how check the properties, in other words
hasOwnPropertywill only return true if key is available on that object directly, howeverinoperator doesn't discriminate between properties created on an object and properties inherited from the prototype chain.
这两个方法检查属性的深度不同,换句话说 hasOwnProperty 只有在本身直接有这个属性的时候返回 true ,但是 in 不会去区分这个熟悉是来自于这个对象本身还是从原型链上继承下来的。
Here another example
这儿有另外的一个例子
var myFunc = function() {
this.name = '@tips_js';
};
myFunc.prototype.age = '10 days';
var user = new myFunc();
user.hasOwnProperty('name'); // true
user.hasOwnProperty('age'); // false, because age is from the prototype chainCheck here the live examples!
Also recommends read this discussion about common mistakes at checking properties' existence in objects
同样也建议你阅读关于检查对象是否包含属性的常见错误的讨论。
2016-01-09 by @JakeRawr
As of ES6, JS now has template strings as an alternative to the classic end quotes strings.
在 ES6 中,JS 现在有模板字符串来替换经典的以引号作为始末的字符串。
Ex:
Normal string
例如:
普通的字符串
var firstName = 'Jake';
var lastName = 'Rawr';
console.log('My name is ' + firstName + ' ' + lastName);
// My name is Jake RawrTemplate String
模板字符串
var firstName = 'Jake';
var lastName = 'Rawr';
console.log(`My name is ${firstName} ${lastName}`);
// My name is Jake RawrYou can do Multi-line strings without
\nand simple logic (ie 2+3) inside${}in Template String.
你可以在不用 \n 的情况下使用多行字符串,除此之外还包括简单的逻辑(例如:2+3)。 在模板字符串里面用 ${} 就可以做到。
You are also able to to modify the output of template strings using a function; they are called Tagged template strings for example usages of tagged template strings.
你也可以通过函数修改模板字符串,具体可以参见 标签模板字符串。
You may also want to read to understand template strings more
你可以能想通过阅读他获取更多模板字符串的内容。
2016-01-08 by @Tevko
The
querySelectorAllmethod returns an array-like object called a node list. These data structures are referred to as "Array-like", because they appear as an array, but can not be used with array methods likemapandforeach. Here's a quick, safe, and reusable way to convert a node list into an Array of DOM elements:
querySelectorAll 方法返回了一个类似数组的对象—— 节点列表(node list)。这个数据结构看起来是 ”类数组“的。因为他们是以一个数组的形式显示的,但是并不是使用数组的一些方法,比如 map 和 foreach。 这儿有一个快速,安全,可重读使用的方法去把一个节点列表转化为 DOM 元素的数组。
const nodelist = document.querySelectorAll('div');
const nodelistToArray = Array.apply(null, nodelist);
//later on ..
nodelistToArray.forEach(...);
nodelistToArray.map(...);
nodelistToArray.slice(...);
//etc...The
applymethod is used to pass an array of arguments to a function with a giventhisvalue. MDN states thatapplywill take an array like object, which is exactly whatquerySelectorAllreturns. Since we don't need to specify a value forthisin the context of the function, we pass innullor0. The result is an actual array of DOM elements which contains all of the available array methods.
apply 方法被用来将数组参数传递给一个给定 this 的函数。 MDN 规定,apply 将得到一个类似对象的数组,他正是 querySelectorAll 返回的东西。因为我们不需要在函数的上下文中指定 this 这个值,所以我们用 null 或者 0 。其结果是一个包含所有可用的数组方法的 DOM 元素的数组。
Or if you are using ES2015 you can use the spread operator
...
如果你使用 ES2015,你可以使用 ... 这个操作符。
const nodelist = [...document.querySelectorAll('div')]; // returns a real Array
//later on ..
nodelist.forEach(...);
nodelist.map(...);
nodelist.slice(...);
//etc...2016-01-07 by @nainslie
Strict-mode JavaScript makes it easier for the developer to write "secure" JavaScript.
严格模式让开发者能够更加容易的写出 “安全” 的 JavaScript 代码。
By default, JavaScript allows the programmer to be pretty careless, for example, by not requiring us to declare our variables with "var" when we first introduce them. While this may seem like a convenience to the unseasoned developer, it's also the source of many errors when a variable name is misspelled or accidentally referred to out of its scope.
默认的情况下,JavaScript 允许程序员非常的不小心,举个例子,第一次使用的时候不需要使用 var 来申明一个变量。虽然这看起来方便了经验丰富的开发,但是事实上,当一个变量名拼写错误或者意外地超出了他的作用域也是很多错误的源头。
Programmers like to make the computer do the boring stuff for us, and automatically check our work for mistakes. That's what the JavaScript "use strict" directive allows us to do, by turning our mistakes into JavaScript errors.
程序员们喜欢让电脑去代替他们做一些无聊的事,并且去自动的检查我们工作中的失误。这就是 JavaScript 中的严格模式指令允许我们去做的事,通过他可以将我们的失误转化为 JavaScript 中的错误。
We add this directive either by adding it at the top of a js file:
我们在文件的顶部添加这样的指令
// Whole-script strict mode syntax
"use strict";
var v = "Hi! I'm a strict mode script!";or inside a function:
或者在函数里面:
function f()
{
// Function-level strict mode syntax
'use strict';
function nested() { return "And so am I!"; }
return "Hi! I'm a strict mode function! " + nested();
}
function f2() { return "I'm not strict."; }By including this directive in a JavaScript file or function, we will direct the JavaScript engine to execute in strict mode which disables a bunch of behaviors that are usually undesirable in larger JavaScript projects. Among other things, strict mode changes the following behaviors:
在 JavaScript 的文件或函数中加入这个指令,我们能直接让 JavaScript 的引擎在严格模式下禁用一系列的在大型项目中不可取的行为。除此之外,严格模式改变了以下的行为:
-
Variables can only be introduced when they are preceded with "var"
变量引入的时间前面必须有
var。 -
Attempting to write to readonly properties generates a noisy error
试图写只读属性的时候会产生错误 。
-
You have to call constructors with the "new" keyword
你必须用
new关键词来调用构造函数。 -
"this" is not implicitly bound to the global object
this不绑定全局对象。 -
Very limited use of eval() allowed
限制使用
eval()。 -
Protects you from using reserved words or future reserved words as variable names
阻止你使用保留字或者将来会用作保留字的单词作为变量名。
Strict mode is great for new projects, but can be challenging to introduce into older projects that don't already use it in most places. It also can be problematic if your build chain concatenates all your js files into one big file, as this may cause all files to execute in strict mode.
在一个新的项目中使用严格模式是非常友好的,但是在大多数地方引入旧项目往往是有些困难的。 如果你编译所有的 js 文件到一个大文件中极有可能是存在问题的,应为这很可能导致所有的文件都在严格模式下执行。
It is not a statement, but a literal expression, ignored by earlier versions of JavaScript.
这不是一个申明,是一个文字的表示式,在早期版本的 JavaScript 中会被忽略。
Strict mode is supported in:
严格模式在以下的环境中被支持:
-
Internet Explorer from version 10.
10 以后的IE
-
Firefox from version 4.
4 以后的 FireFox
-
Chrome from version 13.
13 以后的 Chrome
-
Safari from version 5.1.
5.1 以后的Safari
-
Opera from version 12.
12 以后的Opera
See MDN for a fuller description of strict mode.
2016-01-06 by @mattfxyz
Rather than writing separate methods to handle an array and a single element parameter, write your functions so they can handle both. This is similar to how some of jQuery's functions work (
csswill modify everything matched by the selector).
不像编写一个单独的函数去处理数组或者单一元素,去尝试写一个能同时处理他们的方法。这和 jQuery 中的函数是如何工作是类似的。(css 将修改所有和他选择器匹配的东西)
You just have to concat everything into an array first.
Array.concatwill accept an array or a single element.
你不得不去首先合并数组中的一切东西。 Array.concat 将会接收一个数组或者单一元素。
function printUpperCase(words) {
var elements = [].concat(words);
for (var i = 0; i < elements.length; i++) {
console.log(elements[i].toUpperCase());
}
}
printUpperCaseis now ready to accept a single node or an array of nodes as its parameter.
printUpperCase 现在接收一个单一的元素或者数组中的元素作为他的参数。
printUpperCase("cactus");
// => CACTUS
printUpperCase(["cactus", "bear", "potato"]);
// => CACTUS
// BEAR
// POTATO2016-01-05 by @loverajoel
-
undefinedmeans a variable has not been declared, or has been declared but has not yet been assigned a valueundefined是指一个变量没有被定义,或者是已经定义了但是还没有被赋值。 -
nullis an assignment value that means "no value"null是指一个赋值了的变量,给他赋的值是 “没有值”。 -
Javascript sets unassigned variables with a default value of
undefinedJavaScript给没有赋值的变量分配的默认值是
undefined。 -
Javascript never sets a value to
null. It is used by programmers to indicate that avarhas no value.JavaScript 从来没有给任何一个变量赋值
null。 他用于由程序员申明一个变量没有值。 -
undefinedis not valid in JSON whilenullisundefined在 JSON 中是不符合规范的,但null是可以的。 -
undefinedtypeof isundefinedundefined的类型就是undefined。 -
nulltypeof is anobjectnull的类型是object。 -
Both are primitives
他们两个都是基本类型
-
Both are falsy
他们两个转化为布尔后都是false。
(
Boolean(undefined) // false,Boolean(null) // false) -
You can know if a variable is undefined
假如一个变量是
undefined的话你是可以知道他的。typeof variable === "undefined"
You can check if a variable is null
你是可以检测一个变量是不是
null。variable === null
-
The equality operator considers them equal, but the identity doesn't
等于运算符
==认为他们是相等的,但是身份运算符===认为他们不是相等的。null == undefined // true null === undefined // false
2016-01-04 by @loverajoel
Javascript has a native method sort that allows sorting arrays. Doing a simple
array.sort()will treat each array entry as a string and sort it alphabetically. Also you can provide your own custom sorting function.
JavaScript 拥有一个原生的 sort 排序方法开排序数组。使用简单的 array.sort() 会把数组中的每项当做一个字符串,然后按照字母的顺序进行排序。当然,你也可以使用你自己定义的排序函数。
['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort();
// ["Buenos Aires", "Mumbai", "New York", "Shanghai"]But when you try order an array of non ASCII characters like this
['é', 'a', 'ú', 'c'], you will obtain a strange result['c', 'e', 'á', 'ú']. That happens because sort works only with english language.
但是当你排序不是ASCII字符的数组时,比如这样的 ['é', 'a', 'ú', 'c'] , 你将会得到这样一个奇怪的结果 ['c', 'e', 'á', 'ú']。这是因为排序仅仅适用于英语。
See the next example:
看下面的例子:
// Spanish
['único','árbol', 'cosas', 'fútbol'].sort();
// ["cosas", "fútbol", "árbol", "único"] // bad order
// German
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort();
// ["Wann", "Woche", "wäre", "wöchentlich"] // bad orderFortunately, there are two ways to overcome this behavior localeCompare and Intl.Collator provided by ECMAScript Internationalization API.
幸运的是,这儿有两种由 ECMAScript 国际化 API 提供的方式可以克服这种行为——localeCompare 和 Intl.Collator。
Both methods have their own custom parameters in order to configure it to work adequately.
这两种方法都有可以自定义的参数去配置他来使得他充分工作。
['único','árbol', 'cosas', 'fútbol'].sort(function (a, b) {
return a.localeCompare(b);
});
// ["árbol", "cosas", "fútbol", "único"]
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(function (a, b) {
return a.localeCompare(b);
});
// ["Wann", "wäre", "Woche", "wöchentlich"]['único','árbol', 'cosas', 'fútbol'].sort(Intl.Collator().compare);
// ["árbol", "cosas", "fútbol", "único"]
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collator().compare);
// ["Wann", "wäre", "Woche", "wöchentlich"]-
For each method you can customize the location
每种方法你都可以自定义位置
-
According to Firefox Intl.Collator is faster when comparing large numbers of strings.
当比较两个比较大的字符串的时候
Intl.Collator是更快的。
So when you are working with arrays of strings in a language other than English, remember to use this method to avoid unexpected sorting.
所以当你处理的数组中的字符串不是英文的时候,记得去使用这种方法来避免产生不期待的排序。
2016-01-03 by AlbertoFuente
How can we improve and make more efficient nested
ifstatement in javascript.
我们如何在 JavaScript 中去改善,或者是使我们的if嵌套更加有效。
if (color) {
if (color === 'black') {
printBlackBackground();
} else if (color === 'red') {
printRedBackground();
} else if (color === 'blue') {
printBlueBackground();
} else if (color === 'green') {
printGreenBackground();
} else {
printYellowBackground();
}
}One way to improve the nested
ifstatement would be using theswitchstatement. Although it is less verbose and is more ordered, It's not recommended to use it because it's so difficult to debug errors, here's why.
一种去改善if嵌套的方法可能是使用switch语句。虽然这样做的确看起来更加的有序和简洁,但是并不建议去使用它,因为使用它是如此的难以调试错误,原因在这儿why。
switch(color) {
case 'black':
printBlackBackground();
break;
case 'red':
printRedBackground();
break;
case 'blue':
printBlueBackground();
break;
case 'green':
printGreenBackground();
break;
default:
printYellowBackground();
}But what if we have a conditional with several checks in each statement? In this case, if we like to do less verbose and more ordered, we can use the conditional
switch. If we passtrueas parameter to theswitchstatement, It allows us to put a conditional in each case.
但是如果我们有有一个条件,然后在每个语句进行多项的检查。在这种情况下,如果我们喜欢让嵌套变得更加有序和简洁,我们可以使用这种条件switch。如果我们传递 true 参数给switch 语句,他将允许我们在每一种情况下都有条件。
switch(true) {
case (typeof color === 'string' && color === 'black'):
printBlackBackground();
break;
case (typeof color === 'string' && color === 'red'):
printRedBackground();
break;
case (typeof color === 'string' && color === 'blue'):
printBlueBackground();
break;
case (typeof color === 'string' && color === 'green'):
printGreenBackground();
break;
case (typeof color === 'string' && color === 'yellow'):
printYellowBackground();
break;
}But we must always avoid having several checks in every condition, avoiding use of
switchas far as possible and take into account that the most efficient way to do this is through anobject.
但是我们必须避免在每个条件下都有多次的检查,尽可能的去避免使用switch,解决这个问题最有效的一个方法是通过对象。
var colorObj = {
'black': printBlackBackground,
'red': printRedBackground,
'blue': printBlueBackground,
'green': printGreenBackground,
'yellow': printYellowBackground
};
if (color && colorObj.hasOwnProperty(color)) {
colorObj[color]();
}Here you can find more information about this.
在这儿你将找到更多与这个相关的资料。
2016-01-02 by @loverajoel
The key is an attribute that you must pass to all components created dynamically from an array. It's unique and constant id that React use for identify each component in the DOM and know that it's a different component and not the same one. Using keys will ensure that the child component is preserved and not recreated and prevent that weird things happens.
Key is not really about performance, it's more about identity (which in turn leads to better performance). randomly assigned and changing values are not identity Paul O’Shannessy
- Use an existing unique value of the object.
- Define the keys in the parent components, not in child components
```javascript
//bad
...
render() {
<div key={{item.key}}>{{item.name}}</div>
}
...
//good
<MyComponent key={{item.key}}/>
```
- Using array index is a bad practice.
random()will not work
```javascript
//bad
<MyComponent key={{Math.random()}}/>
```
- You can create your own unique id, be sure that the method be fast and attach it to your object.
- When the amount of child are big or involve expensive components, use keys has performance improvements.
- You must provide the key attribute for all children of ReactCSSTransitionGroup.
2016-01-01 by @loverajoel
One of the most appreciated features of AngularJs is the two way data binding. In order to make this work AngularJs evaluates the changes between the model and the view through cycles(
$digest). You need to understand this concept in order to understand how the framework works under the hood.
AngularJs 中最让人欣赏的莫过于数据的双向绑定。AngularJs 在模型和视图之间通过循环视图使得这一机制实现。如果你想去理解框架是如何去工作的话你需要了解这一概念。
Angular evaluates each watcher whenever one event is fired, this is the known
$digestcycle.Sometimes you have to force to run a new cycle manually and you must choose the correct option because this phase is one of the most influential in terms of performance.
Angular 中每当一个事件被触发,就形成一个已知的$digest cycle。有时候你不得不去强制手动创建一个新的周期,这个时候你必须有正确的选择,因为这个阶段对性能的影响是非常之大的。
This core method lets you to start the digestion cycle explicitly, that means that all watchers are checked, the entire application starts the
$digest loop. Internally after execute an optional function parameter, call internally to$rootScope.$digest();.
这个核心的方法让你去明确的开始$digest cycle,这就意味着所有的watchers都会重新进行检查,整个应用启动$digest loop。 经过内部执行可选的函数参数,调用内部的$rootScope.$digest();。
In this case the
$digestmethod starts the$digestcycle for the current scope and its children. You should notice that the parents scopes will not be checked and not be affected.
在这样的情况下,$digest方法从当前的作用域以及子作用域中启动 $digest cycle。你应该能注意到父作用域将不会进行检查,当然也就没有影响。
-
Use
$applyor$digestonly when browser DOM events have triggered outside of AngularJS.仅仅当浏览器的 DOM 事件在 AngularJs 作用的外面时使用
$apply或者$digest。 -
Pass a function expression to
$apply, this have a error handling mechanism and allow integrate changes in the digest cycle给
$apply传递一个函数表达式的时候,有一个错误处理机制,这个机制允许集成 digest cycle 的变化。
```javascript
$scope.$apply(() => {
$scope.tip = 'Javascript Tip';
});
```
-
If only needs update the current scope or its children use
$digest, and prevent a new digest cycle for the whole application. The performance benefit it's self evident仅仅去更新现在的作用域或者子作用域的时候使用
$digest,阻止整个应用产生新的 digest cycle 。这在性能上的好处是不言而喻的。 -
$apply()is hard process for the machine and can lead to performance issues when having a lot of binding.$apply()是一个很难用的方法,当许多的绑定放在一起的时候可能会在性能上产生问题。 -
If you are using >AngularJS 1.2.X, use
$evalAsyncis a core method that will evaluate the expression during the current cycle or the next. This can improve your application's performance.如果你使用的 AngularJS 版本是大于 1.2.X的,使用核心方法
$evalAsync在当前的周期或者下一个的时候。这将提升你的应用性能。
2015-12-29
Inserting an item into an existing array is a daily common task. You can add elements to the end of an array using push, to the beginning using unshift, or the middle using splice.
在一个已经存在的数组中插入一个元素是我们每天都要做的事情,你可以用push操作把这个元素插入到数组的最后面,使用unshift操作把它插入到数据的最前面,或者使用splice 把它插入到数组的中间。
But those are known methods, doesn't mean there isn't a more performant way, here we go...
这些都是我们熟知的方法,但是这并不意味这没有一个性能更好的方法, 现在,跟着我一起去看看...
Adding an element at the end of the array is easy with push(), but there is a way more performant.
用push 方法能把一个元素非常方便的插入到数据的最后面,但是这个有一种性能上更好的方法去达到同样的目的。
var arr = [1,2,3,4,5];
arr.push(6);
arr[arr.length] = 6; // 这种方法在 OS X 10.11.1 的 Chrome 47.0.2526.106 上要比直接push要快43%(43% faster in Chrome 47.0.2526.106 on Mac OS X 10.11.1)Both methods modify the original array. Don't believe me? Check the jsperf
去试试利用这两种方法修改数据。不相信我,看看这个jsperf
Now we are trying to add an item to the beginning of the array
现在我们去尝试在数据的最前面加入一个元素
var arr = [1,2,3,4,5];
arr.unshift(0);
[0].concat(arr); // 这种方法在 OS X 10.11.1 的 Chrome 47.0.2526.106 上要比unshift快98% (faster in Chrome 47.0.2526.106 on Mac OS X 10.11.1)Here is a little bit detail, unshift edits the original array, concat returns a new array. jsperf
这儿有一个小小的细节,unshift修改的是原始的数据,concat返回的是一个新的数组。jsperf
Adding items at the middle of an array is easy with splice and is the most performant way to do it.
用splice去把一个元素插入到数组的中间不仅仅是最简单的方法,同样也是性能上最好的方法。
var items = ['one', 'two', 'three', 'four'];
items.splice(items.length / 2, 0, 'hello');I tried to run these tests in various Browsers and OS and the results were similar. I hope these tips will be useful for you and encourage to perform your own tests!
我试着去在不同的浏览器和操作系统上测试上面所说的东西,结果都是一致的。我希望这个技巧对你是有用的,同时我也鼓励你去尝试他。

