JavaScript is a world-leading programming language that can be used for web development, mobile application development (PhoneGap, Appcelerator), and server-side development (Node.jsand Wakanda) and so on. JavaScript is also the first language for many novices to enter the world of programming. It can be used to display a simple prompt box in the browser, or to control the robot through nodebot or nodruino. Developers who can write JavaScript code with clear structure and high performance are now the most sought after people in the recruitment market.
In this article, I will share some JavaScript tips, secrets, and best practices that, with a few exceptions, apply to both the browser's JavaScript engine and the server-side JavaScript interpreter.
The sample code in this article passed the test on the latest version of Google Chrome 30 (V8 3.20.17.15).
var
keywordIf the variable is not declared and assigned directly, it will be used as a new value by default. Global variables, try to avoid using global variables.
===
instead of ==
==
and !=
Operators will automatically convert data types if necessary. But ===
and !==
will not, they will compare the value and data type at the same time, which also makes them better than ==
and !=
Fast. The logical results of
[10] === 10 // is false [10] == 10 // is true '10' == 10 // is true '10' === 10 // is false [] == 0 // is true [] === 0 // is false '' == false // is true but true == "a" is false '' === false // is false
underfined
, <a href="//m.sbmmt.com/wiki/62.html" target="_blank">null</a>
, 0, false, NaN, empty string are all For falseIn practice, it is best to use a semicolon. It doesn’t matter if you forget to write it. In most cases, the JavaScript interpreter will automatically add it. For more information on why semicolons are used, please refer to the article The Truth About Semicolons in JavaScript.
function Person(firstName, lastName){ this.firstName = firstName; this.lastName = lastName; } var Saad = new Person("Saad", "Mousliki");
typeof
, instanceof
and contructor# carefully
##typeof: JavaScript unary operator, used to return the original type of the variable in the form of a string. Note,
typeof null
object<a href="//m.sbmmt.com/wiki/60.html" target="_blank"></a> will also be returned. Most object types (
arrayArray, timeDate, etc.) will also return object
contructor: Internal prototype
properties , which can be overridden by code
instanceof: JavaScript operator, it will
search for in the constructor in the prototype chain, and return true if found, otherwise
false## will be returned.
var arr = ["a", "b", "c"]; typeof arr; // 返回 "object" arr instanceof Array // true arr.constructor(); //[]
(Self-Invoked Anonymous Function) or directly call Function Expression(Immediately Invoked Function Expression). The format is as follows: (function(){
// 置于此处的代码将自动执行
})();
(function(a,b){
var result = a+b;
return result;
})(10,20)
var items = [12, 548 , 'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' , 2145 , 119]; var randomItem = items[Math.floor(Math.random() * items.length)];
var x = Math.floor(Math.random() * (max - min + 1)) + min;
10. Generate a numeric array from 0 to the specified value
var numbersArray = [] , max = 100; for( var i=1; numbersArray.push(i++) < max;); // numbers = [1,2,3 ... 100]
function generateRandomAlphaNum(len) { var rdmString = ""; for( ; rdmString.length < len; rdmString += Math.random().toString(36).substr(2)); return rdmString.substr(0, len); }
var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; numbers = numbers.sort(function(){ return Math.random() - 0.5}); /* numbers 数组将类似于 [120, 5, 228, -215, 400, 458, -85411, 122205] */
function of JavaScript is used here. A better way is to use special code to implement it (such as Fisher-Yates algorithm), you can see StackOverFlow## This discussion on #. 13. String spaces removal
Java,trim function for the
String object: <a href="//m.sbmmt.com/wiki/1438.html" target="_blank"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">String.prototype.trim = function(){return this.replace(/^\s+|\s+$/g, "");};</pre><div class="contentsignin">Copy after login</div></div></a>The new JavaScript engine already has
trim( )
var array1 = [12 , "foo" , {name "Joe"} , -2458]; var array2 = ["Doe" , 555 , 100]; Array.prototype.push.apply(array1, array2); /* array1 值为 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
var argArray = Array.prototype.slice.call(arguments);
function isNumber(n){ return !isNaN(parseFloat(n)) && isFinite(n); }
function isArray(obj){ return Object.prototype.toString.call(obj) === '[object Array]' ; }
但如果toString()
方法被重写过得话,就行不通了。也可以使用下面的方法:
Array.isArray(obj); // its a new Array method
如果在浏览器中没有使用frame,还可以用instanceof
,但如果上下文太复杂,也有可能出错。
var myFrame = document.createElement('iframe'); document.body.appendChild(myFrame); var myArray = window.frames[window.frames.length-1].Array; var arr = new myArray(a,b,10); // [a,b,10] // myArray 的构造器已经丢失,instanceof 的结果将不正常 // 构造器是不能跨 frame 共享的 arr instanceof Array; // false
var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; var maxInNumbers = Math.max.apply(Math, numbers); var minInNumbers = Math.min.apply(Math, numbers);
var myArray = [12 , 222 , 1000 ]; myArray.length = 0; // myArray will be equal to [].
<a href="//m.sbmmt.com/wiki/1298.html" target="_blank">delete</a>
或remove
元素如果对数组元素直接使用delete
,其实并没有删除,只是将元素置为了undefined
。数组元素删除应使用splice
。
切忌:
var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ]; items.length; // return 11 delete items[3]; // return true items.length; // return 11 /* items 结果为 [12, 548, "a", undefined × 1, 5478, "foo", 8852, undefined × 1, "Doe", 2154, 119] */
而应:
var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ]; items.length; // return 11 items.splice(3,1) ; items.length; // return 10 /* items 结果为 [12, 548, "a", 5478, "foo", 8852, undefined × 1, "Doe", 2154, 119]
删除对象的属性时可以使用delete
。
length
属性截断数组前面的例子中用length
属性清空数组,同样还可用它来截断数组:
var myArray = [12 , 222 , 1000 , 124 , 98 , 10 ]; myArray.length = 4; // myArray will be equal to [12 , 222 , 1000 , 124].
与此同时,如果把length
属性变大,数组的长度值变会增加,会使用undefined
来作为新的元素填充。length
是一个可写的属性。
myArray.length = 10; // the new array length is 10 myArray[myArray.length - 1] ; // undefined
var foo = 10; foo == 10 && doSomething(); // is the same thing as if (foo == 10) doSomething(); foo == 5 || doSomething(); // is the same thing as if (foo != 5) doSomething();
逻辑或还可用来设置默认值,比如函数参数的默认值。
function doSomething(arg1){ arg1 = arg1 || 10; // arg1 will have 10 as a default value if it’s not already set }
<a href="//m.sbmmt.com/code/9794.html" target="_blank">map</a>()
函数方法对数据循环var squares = [1,2,3,4].map(function (val) { return val * val; }); // squares will be equal to [1, 4, 9, 16]
var num =2.443242342; num = num.toFixed(4); // num will be equal to 2.4432
注意,toFixec()
返回的是字符串,不是数字。
0.1 + 0.2 === 0.3 // is false 9007199254740992 + 1 // is equal to 9007199254740992 9007199254740992 + 2 // is equal to 9007199254740994
为什么呢?因为0.1+0.2等于0.30000000000000004。JavaScript的数字都遵循IEEE 754标准构建,在内部都是64位浮点小数表示,具体可以参见JavaScript中的数字是如何编码的.
可以通过使用toFixed()
和<a href="//m.sbmmt.com/wiki/904.html" target="_blank">toP</a>recision()
来解决这个问题。
下面这样的用法,可以防止迭代的时候进入到对象的原型属性中。
for (var name in object) { if (object.hasOwnProperty(name)) { // do something with name } }
var a = 0; var b = ( a++, 99 ); console.log(a); // a will be equal to 1 console.log(b); // b is equal to 99
在jQuery选择器中,可以临时存储整个DOM元素。
var navright = document.querySelector('#right'); var navleft = document.querySelector('#left'); var navup = document.querySelector('#up'); var navdown = document.querySelector('#down');
isFinite()
的参数isFinite(0/0) ; // false isFinite("foo"); // false isFinite("10"); // true isFinite(10); // true isFinite(undefined); // false isFinite(); // false isFinite(null); // true,这点当特别注意
var numbersArray = [1,2,3,4,5]; var from = numbersArray.indexOf("foo") ; // from is equal to -1 numbersArray.splice(from,2); // will return [5]
注意传给splice
的索引参数不要是负数,当是负数时,会从数组结尾处删除元素。
var person = {name :'Saad', age : 26, department : {ID : 15, name : "R&D"} }; var stringFromPerson = JSON.stringify(person); /* stringFromPerson 结果为 "{"name":"Saad","age":26,"department":{"ID":15,"name":"R&D"}}" */ var personFromString = JSON.parse(stringFromPerson); /* personFromString 的值与 person 对象相同 */
eval()
或者函数构造器eval()
和函数构造器(Function
consturctor)的开销较大,每次调用,JavaScript引擎都要将源代码转换为可执行的代码。
var func1 = new Function(functionCode); var func2 = eval(functionCode);
eval()
或者函数构造器eval()
和函数构造器(Function
consturctor)的开销较大,每次调用,JavaScript引擎都要将源代码转换为可执行的代码。
var func1 = new Function(functionCode); var func2 = eval(functionCode);
with()
使用with()
可以把变量加入到全局作用域中,因此,如果有其它的同名变量,一来容易混淆,二来值也会被覆盖。
避免:
var sum = 0; for (var i in arrayNumbers) { sum += arrayNumbers[i]; }
而是:
var sum = 0; for (var i = 0, len = arrayNumbers.length; i < len; i++) { sum += arrayNumbers[i]; }
另外一个好处是,i
和len
两个变量是在for
循环的第一个声明中,二者只会初始化一次,这要比下面这种写法快:
for (var i = 0; i < arrayNumbers.length; i++)
setInterval()
和set<a href="//m.sbmmt.com/wiki/1268.html" target="_blank">Time</a>out()
时使用函数而不是字符串如果传给setTimeout()
和setInterval()
一个字符串,他们将会用类似于eval
方式进行转换,这肯定会要慢些,因此不要使用:
setInterval('doSomethingPeriodically()', 1000); setTimeout('doSomethingAfterFiveSeconds()', 5000);
而是用:
setInterval(doSomethingPeriodically, 1000); setTimeout(doSomethingAfterFiveSeconds, 5000);
<a href="//m.sbmmt.com/wiki/132.html" target="_blank">switch</a>/case
代替一大叠的if/<a href="//m.sbmmt.com/wiki/111.html" target="_blank">else</a>
当判断有超过两个分支的时候使用switch/case
要更快一些,而且也更优雅,更利于代码的组织,当然,如果有超过10个分支,就不要使用switch/case
了。
switch/case
中使用数字区间其实,switch/case
中的case
条件,还可以这样写:
function getCategory(age) { var category = ""; switch (true) { case isNaN(age): category = "not an age"; break; case (age >= 50): category = "Old"; break; case (age <= 20): category = "Baby"; break; default: category = "Young"; break; }; return category; } getCategory(5); // 将返回 "Baby"
下面这样,便可以给定对象作为参数,来创建以此为原型的新对象:
function clone(object) { function OneShotConstructor(){}; OneShotConstructor.prototype = object; return new OneShotConstructor(); } clone(Array).prototype ; // []
function escapeHTML(text) { var replacements= {"<": "<", ">": ">","&": "&", "\"": """}; return text.replace(/[<>&"]/g, function(character) { return replacements[character]; }); }
try-catch-finally中catch部分在执行时会将异常赋给一个变量,这个变量会被构建成一个运行时作用域内的新的变量。
切忌:
var object = ['foo', 'bar'], i; for (i = 0, len = object.length; i <len; i++) { try { // do something that throws an exception } catch (e) { // handle exception } }
而应该:
var object = ['foo', 'bar'], i; try { for (i = 0, len = object.length; i <len; i++) { // do something that throws an exception } } catch (e) { // handle exception }
XMLHttpRequests在执行时,当长时间没有响应(如出现网络问题等)时,应该中止掉连接,可以通过setTimeout()
来完成这个工作:
var xhr = new XMLHttpRequest (); xhr.onreadystatechange = function () { if (this.readyState == 4) { clearTimeout(timeout); // do something with response data } } var timeout = setTimeout( function () { xhr.abort(); // call error callback }, 60*1000 /* timeout after a minute */ ); xhr.open('GET', url, true); xhr.send();
同时需要注意的是,不要同时发起多个XMLHttpRequests请求。
通常情况下,WebSocket连接创建后,如果30秒内没有任何活动,服务器端会对连接进行超时处理,防火墙也可以对单位周期没有活动的连接进行超时处理。
为了防止这种情况的发生,可以每隔一定时间,往服务器发送一条空的消息。可以通过下面这两个函数来实现这个需求,一个用于使连接保持活动状态,另一个专门用于结束这个状态。
var timerID = 0; function keepAlive() { var timeout = 15000; if (webSocket.readyState == webSocket.OPEN) { webSocket.send(''); } timerId = setTimeout(keepAlive, timeout); } function cancelKeepAlive() { if (timerId) { cancelTimeout(timerId); } }
keepAlive()
函数可以放在WebSocket连接的onOpen()
方法的最后面,cancelKeepAlive()
放在onClose()
方法的最末尾。
比如,一般不要这样:
var min = Math.min(a,b); A.push(v);
可以这样来代替:
var min = a < b ? a : b; A[A.length] = v;
别忘了在写代码时使用一个代码美化工具。使用JSLint(一个语法检查工具)并且在上线前压缩代码(比如使用JSMin)。注:现在代码压缩一般推荐 UglifyJS (//m.sbmmt.com/)
Code Academy资源:http://www.codecademy.com/tracks/javascript
Marjin Haverbekex编写的Eloquent JavaScript:http://eloquentjavascript.net/
John Resig编写的Advanced JavaScript:http://ejohn.org/apps/learn/
The above is the detailed content of 45 classic tips for JavaScript development. For more information, please follow other related articles on the PHP Chinese website!