首頁 >後端開發 >php教程 >js一些小技巧分享

js一些小技巧分享

小云云
小云云原創
2018-03-20 16:43:251572瀏覽

本文主要跟大家分享js一些小技巧,文章有點長,希望能幫助大家。

1、javascript 容錯處理程式碼(屏蔽js錯誤)

<span style="font-size: 14px;"><script language="javascript"><br/>    <!--    /*屏蔽所有的js错误*/<br/>    function killerrors() {<br/>        return true;<br/>    }<br/>    window.onerror = killerrors;    //--></script><br/></span>

能夠提供大家這些簡短而實用的JavaScript技巧來提升大家程式設計能力,這對我來說是件很開心的事。每天只花上不到2分鐘的時間中,你將可以讀遍JavaScript這門可怕的語言所呈現給我們的特性:performance(性能), conventions(協議), hacks(代碼hack), interview questions(面試問題)及所有其他的項。

2、 使用=== 代替==

==(或!=)做比較的時候會比較的兩者轉換到同一類型再比較。 ===(或!==)則不會,他會將進行對比的兩者做類型對比和值對比,相對於 == ,=== 的對比會更加嚴謹。
[10] == 10 // true
[10] === 10 // false
“10” == 10 // true
“10” === 10 // false
[] == 0 // true
[] === 0 // false
“” == false // true 但是true == “a” 是false
“” == = false // false

3、轉換數值的更加的方法

將字串轉換為數字是非常常見的。最簡單和最快的(jspref)的方式來實現,將使用+(加)演算法。

var one = '1';
var numberOne = +one; // Number 1

你也可以使用-(減號)演算法的轉換類型並且變成負數值。

var one = '1';
var negativeNumberOne = -one; // Number -1

##4 - 清除一個陣列<span style="font-size: 14px;"></span>

你定義一個數組,並且希望清空它的內容。通常,你會這樣做:<span style="font-size: 14px;"></span>

var list = [1, 2, 3, 4]; 
function empty() { 
//清空数组 
list = []; 
} 
empty();
但是还有一种更高性能的方法。
你可以使用这些代码: 
var list = [1, 2, 3, 4]; 
function empty() { 
//清空数组 
list.length = 0; 
} 
empty();
· list =[] 将一个变量指定个引用到那个数组,而其他引用都不受影响。这意味着,对于先前数组的内容的引用仍然保留在内存中,从而导致内存泄漏。 
· list.length = 0 删除数组内的所有东西,这不需要引用任何其他的东西 
然而,如果你有一个copy的数组(A和copy-A),如果你使用list.length = 0 删除其内容,副本也会失去它的内容。 
var foo = [1,2,3]; 
var bar = [1,2,3]; 
var foo2 = foo; 
var bar2 = bar; 
foo = []; 
bar.length = 0; 
console.log(foo, bar, foo2, bar2); 
//[] [] [1, 2, 3] []

StackOverflow上的更多詳情:<span style="font-size: 14px;"></span>

function shuffle(arr) { 
var i, 
j, 
temp; 
for (i = arr.length - 1; i > 0; i–) { 
j = Math.floor(Math.random() * (i + 1)); 
temp = arr[i]; 
arr[i] = arr[j]; 
arr[j] = temp; 
} 
return arr;  
};

StackOverflow上的更多詳情:difference-between-array-length-0-and-array<span style="font-size: 14px;"></span>

#5 - 對陣列排序進行」洗牌」(隨機排序)

這段程式碼在這裡使用Fisher Yates洗牌演算法給一個指定的陣列進行洗牌(隨機排序)。

<span style="font-size: 14px;"></span>

function Person(name) { 
this.name = name; 
this.sayName = function() { 
console.log(“Hello my name is: “, this.name); 
return this; 
}; 
this.changeName = function(name) { 
this.name = name; 
return this; 
}; 
} 
var person = new Person(“John”); 
person.sayName().changeName(“Timmy”).sayName(); 
//Hello my name is: John 
//Hello my name is: Timmy




# 案例:
?
1
2

3

4


var a = [1, 2, 3, 4, 5, 6, 7, 8];
var b = shuffle(a);

console.log(b);

// [2, 7, 8, 6, 5, 3, 1, 4]<span style="font-size: 14px;"></span>

6 - 傳回物件的函數能夠用於鍊式運算<span style="font-size: 14px;"></span>

當建立物件導向的JavaScript物件的function時,函數會傳回一個物件將能夠讓函數可鍊式的寫在一起來執行。 <span style="font-size: 14px;"></span>

// 单位移 
console.log(~1337) // -1338 
// 双位移 
console.log(
47.11) // -> 47 
console.log(
-12.88) // -> -12 
console.log(
1.9999) // -> 1 
console.log(~~3) // -> 3 
//失败的情况 
console.log(
[]) // -> 0  
console.log(
NaN) // -> 0 
console.log(~~null) // -> 0 
//大于32位整数则失败 
console.log(
(2147483647 + 1) === (2147483647 + 1)) // -> 0

<span style="font-size: 14px;"></span>

7 - 字串安全連線<span style="font-size: 14px;"></span>

假設你有一些類型未知的變量,你想將它們連接起來。可以肯定的是,演算法操作不會在級聯時應用:


var one = 1;
var two = 2;

var three = '3';

var result = ”.concat(one, two, three); //”123”<span style="font-size: 14px;"></span>

這樣的連接不正是你所期望的。相反,一些串聯和相加可能會導致意想不到的結果:


var one = 1;
var two = 2;

var three = '3';

var result = one + two + three; //”33” 而不是“123”<span style="font-size: 14px;"></span>

談到性能,對join和concat進行比較,他們的執行速度是幾乎一樣的。在MDN了解更多與concat相關的知識<span style="font-size: 14px;"></span>

8 - 更快的四捨五入

今天的技巧是關於性能。雙波浪線”~~”操作符嗎?位元轉換輸入-(輸入+1),因此雙位移將輸入轉換為-(-(輸入+1)),這是一個趨於0的偉大的工具。取負值和Math.floor()取正值。

<span style="font-size: 14px;"></span>

##雖然~~可能有更好的表現,為了可讀性,請使用Math.floor()。

9 - Node.js:让module在没被require的时候运行

在node里,你可以根据代是运行了require(‘./something.js’)还是node something.js,来告诉你的程序去做两件不同的事情。如果你想与你的一个独立的模块进行交互,这是很有用的。

if (!module.parent) { 
// 运行 
node something.js
 
app.listen(8088, function() { 
console.log(‘app listening on port 8088’); 
}) 
} else { 
// 使用 
require(&#39;/.something.js&#39;)
 
module.exports = app; 
}

<span style="font-size: 14px;"></span>

更多信息,请看the documentation for modules

10 - 给回调函数传递参数

在默认情况下,你无法将参数传给回调函数,如下:

function callback() { 
console.log(‘Hi human’); 
} 
document.getElementById(‘someelem’).addEventListener(‘click’, callback);
你可以采取JavaScript闭包的优点来给回调函数传参,案例如下:
function callback(a, b) { 
return function() { 
console.log(‘sum = ‘, (a+b)); 
} 
} 
var x = 1, y = 2; 
document.getElementById(‘someelem’).addEventListener(‘click’, callback(x, y));

什么是闭包呢?闭包是指一个针对独立的(自由)变量的函数。换句话说,闭包中定义的函数会记住它被创建的环境。了解更多请参阅MDN所以这种方式当被调用的时候,参数X/Y存在于回调函数的作用域内。

另一种方法是使用绑定方法。例如:

var alertText = function(text) { 
alert(text); 
}; 
document.getElementById(‘someelem’).addEventListener(‘click’, alertText.bind(this, ‘hello’));

<span style="font-size: 14px;"></span>

两种方法在性能上有一些略微区别,详情参阅jsperf

11 - 使用更简单的类似indexOf的包含判断方式

原生的JavaScript没有contains方法。对检查字符串或字符串数组项中是否存在某值,你可以这样做:

var someText = ‘JavaScript rules’; 
if (someText.indexOf(‘JavaScript’) !== -1) { 
} 
// 或者 
if (someText.indexOf(‘JavaScript’) >= 0) { 
}

<span style="font-size: 14px;"></span>

但是我们再看看这些ExpressJs代码片段。

// examples/mvc/lib/boot.js 
for (var key in obj) { 
// “reserved” exports 
if (~[‘name’, ‘prefix’, ‘engine’, ‘before’].indexOf(key)) continue;
// examples/lib/utils.js
exports.normalizeType = function(type){
return ~type.indexOf(‘/’)
? acceptParams(type)
{ value: mime.lookup(type), params: {} }; 
};
// examples/web-service/index.js 
// key is invalid 
if (!~apiKeys.indexOf(key)) return next(error(401, ‘invalid api key’));

问题是~位运算符。”运算符执行操作这样的二进制表达式,但他们返回标准的JavaScript的数值.”
他们将-1转换为0,而0在JavaScript中又是false。

var someText = ‘text’; 
!!~someText.indexOf(‘tex’); // someText 包含 “tex” - true 
!~someText.indexOf(‘tex’); // someText 不包含 “tex” - false 
~someText.indexOf(‘asd’); // someText 不包含 “asd” - false 
~someText.indexOf(‘ext’); // someText 包含 “ext” - true 
String.prototype.includes()

<span style="font-size: 14px;"></span>

在ES6(ES 2015)中介绍了includes()方法可以用来确定是否一个字符串包含另一个字符串:

‘something’.includes(‘thing’); // true

在ECMAScript 2016 (ES7)中,甚至数组都可以这样操作,如indexOf:

!!~[1, 2, 3].indexOf(1); // true
[1, 2, 3].includes(1); // true

不幸的是,这只是在Chrome,Firefox,Safari 9或以上的浏览器中被支持。

12 - arrow 函数(ES6)

介绍下ES6里的新功能,arrow函数可能会是个很方便的工具,用更少行数写更多代码。他的名字来源于他的语法,=>和小箭头->比就像一个“胖胖的箭头”。可能有些人知道,这种函数类型和其他静态语言如lambda表达式的匿名函数。它被称为匿名,因为这些箭头函数没有一个描述性的函数名。
那么这样有什么好处呢?

语法:更少的LOC,不用一次次的键入函数关键字。

语义:从上下文中捕捉关键字this。

简单语法案例:

看看下面的两段代码片段,他们做的是一样的工作。你能很快的理解arrow函数的功能。

// arrow函数的日常语法 param => expression // 可能也会写在括号中 // 括号是多参数要求 (param1 [, param2]) => expression
// 使用日常函数 var arr = [5,3,2,9,1]; var arrFunc = arr.map(function(x) { return x * x; }); console.log(arr)
// 使用arrow函数 var arr = [5,3,2,9,1]; var arrFunc = arr.map((x) => x*x); console.log(arr)

<span style="font-size: 14px;"></span>

正如你所看到的,这个例子中的arrow函数可以节省你输入括号内参数和返回关键字的时间。建议把圆括号内的参数输入,如 (x,y) => x+y 。在不同的使用情况下,它只是

用来应对遗忘的一种方式。但是上面的代码也会这样执行:x => x*x.目前看来,这些仅仅是导致更少的LOC和更好的可读性的句法改进。

this 绑定

还有一个更好的理由使用arrow函数。那就是在会出现this问题的背景下。使用arrow函数,你就不用担心.bind(this)和 that=this 了。因为arrow函数会从上下文中找到this。

看下面的例子:

// 全局定义this.i 
this.i = 100; 
var counterA = new CounterA(); 
var counterB = new CounterB(); 
var counterC = new CounterC(); 
var counterD = new CounterD();
// 不好的示例 
function CounterA() { 
// CounterA’s this 实例 (!! 忽略这里) 
this.i = 0; 
setInterval(function () { 
// this 指全局对象,而不是 CounterA’s this 
// 因此,开始计数与100,而不是0 (本地的 this.i) 
this.i++; 
document.getElementById(“counterA”).innerHTML = this.i; 
}, 500); 
} 
// 手动绑定 that = this 
function CounterB() { 
this.i = 0; 
var that = this; 
setInterval(function() { 
that.i++; 
document.getElementById(“counterB”).innerHTML = that.i; 
}, 500); 
} 
// 使用 .bind(this) 
function CounterC() { 
this.i = 0; 
setInterval(function() { 
this.i++; 
document.getElementById(“counterC”).innerHTML = this.i; 
}.bind(this), 500); 
} 
// 使用 arrow函数 
function CounterD() { 
this.i = 0; 
setInterval(() => { 
this.i++; 
document.getElementById(“counterD”).innerHTML = this.i; 
}, 500); 
}

关于arrow函数的进一步信息可以看这里 。查看不同的语法选请访问该站点。

13 - 测量一个JavaScript代码块性能的技巧

快速测量一个JavaScript块的性能,我们可以使用控制台的功能像console.time(label)和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”); // 输出: Array initialize: 0.711ms

<span style="font-size: 14px;"></span>

更多信息Console object, JavaScript benchmarking

demo:jsfiddle-codepen (在浏览器控制台输出)

14 - ES6中参数处理

在许多编程语言中,函数的参数是默认的,而开发人员必须显式定义一个参数是可选的。在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

_err是立即抛出一个错误的函数。如果没有一个参数作为值,默认值是会被使用,_err将被调用,将抛出错误。你可以在Mozilla开发者网络看到的更多默认参数的例子。

15 - 提升

理解提升将帮助你组织你的function。只需要记住,变量声明和定义函数会被提升到顶部。变量的定义是不会的,即使你在同一行中声明和定义一个变量。此外,变量声明让系统知道变量存在,而定义是将其赋值给它。

function doTheThing() { 
// 错误: notDeclared is not defined 
console.log(notDeclared); 
// 输出: undefined 
console.log(definedLater); 
var definedLater; 
definedLater = ‘I am defined!’ 
// 输出: ‘I am defined!’ 
console.log(definedLater) 
// Outputs: undefined 
console.log(definedSimulateneously); 
var definedSimulateneously = ‘I am defined!’ 
// 输出: ‘I am defined!’ 
console.log(definedSimulateneously) 
// 输出: ‘I did it!’ 
doSomethingElse(); 
function doSomethingElse(){ 
console.log(‘I did it!’); 
} 
// 错误: undefined is not a function 
functionVar(); 
var functionVar = function(){ 
console.log(‘I did it!’); 
} 
}

<span style="font-size: 14px;"></span>

为了使事情更容易阅读,在函数作用域内提升变量的声明将会让你明确该变量的声明是来自哪个作用域。在你需要使用变量之前定义它们。在作用域底部定义函数,确保代码清晰规范。

16 - 检查一个对象是否有属性

当你要检查一个对象是否存在某个属性时,你可能会这样做 :

var myObject = {
name: ‘@tips_js’
};
if (myObject.name) { … }

这是可以的,但你必须知道这个还有两原生的方式,in operator 和 object.hasownproperty,每个对象是对象,既可用方法。每个object都继承自Object,这两个方法都可用。

两个方法的一些不同点:

var myObject = {
name: ‘@tips_js’
};
myObject.hasOwnProperty(‘name’); // true
‘name’ in myObject; // true
myObject.hasOwnProperty(‘valueOf’); // false, valueOf 是从原型链继承的
‘valueOf’ in myObject; // true

他们之间的不同在于检查的性质,换句话说,当该对象本身有查找的属性时hasOwnProperty返回yrue,然而,in operator不区分属性创建的对象和属性继承的原型链。
这里有另外一个例子:

var myFunc = function() {
this.name = ‘@tips_js’;
};
myFunc.prototype.age = ‘10 days’;
var user = new myFunc();
user.hasOwnProperty(‘name’); // true
user.hasOwnProperty(‘age’); // false, 因为age是原型链上的

点击看例子。同时,建议在检查对象的属性存在时,阅读这些有关的常见错误。

17 - 模板字符串

截至ES6,JS已经有模板字符串作为替代经典的结束引用的字符串。
案例:普通字符串

var firstName = ‘Jake’;
var lastName = ‘Rawr’;
console.log(‘My name is ’ + firstName + ’ ’ + lastName);
// My name is Jake Rawr  
模板字符串:
var firstName = ‘Jake’;
var lastName = ‘Rawr’;
console.log(
<span style="font-size: 14px;">My name is ${firstName} ${lastName}</span>);
// My name is Jake Rawr

在模板字符串中${}中,你可以写不用写/n或者简单逻辑来实现多行字符串。
您还可以使用函数来修改模板字符串的输出,它们被称为模板字符串的标记。你可能还想读到更多的理解模板字符串相关信息。

18- 將節點清單轉換為陣列

querySelectorAll 方法傳回一個和陣列類似的節點列表物件。這些資料結構類似數組,因為常以數組形式出現,但是又不能用數組的方法,例如map和foreach。這裡是一個快速、安全、可重複使用的方式將一個節點列表到一個DOM元素數組:

const nodelist = document.querySelectorAll('p');
const nodelistToArray = Array.apply(null, nodelist);
//later on ..
nodelistToArray.forEach(…);
nodelistToArray.map(…);
nodelistToArray.slice(…);
//etc…

apply方法是將一系列陣列格式的參數傳遞給一個給定this的函數。 MDN指出,apply將會呼叫類似陣列的對象,而這正是querySelectorAll所傳回的。因為我們不需要在函數的上下文中指定this,所以我們傳入null或0。傳回的結果是一組能使用陣列方法的DOM元素數組。

如果你使用的是es2015可以利用…(spread operator)

const nodelist = […document.querySelectorAll('p') ]; // 回傳的是個真實的陣列
//later on ..
nodelist.forEach(…);
nodelist.map(…);
nodelist.slice(…);
//etc…

19 - “use strict” 和懶惰

嚴格模式的JavaScript讓開發人員更安全的編寫JavaScript 。
預設情況下,JavaScript允許開發者懶惰,例如,我們在第一次宣告變數的時候可以不用var,雖然這可能看起來像一個沒有經驗的開發人員,同時這也是很多錯誤的根源,變數名拼字錯誤或意外地將它提到了外部作用域。

程式設計師喜歡讓電腦為我們做些無聊的事,檢查一些我們工作的錯誤。 「use strict」指令我們來做這些,將我們的錯誤轉換成JavaScript的錯誤。

我們把這個指令可以透過加在一個js檔案的頂部:

// 整個script檔都會是嚴格模式語法
“use strict”;
var v = “Hi! I'm a strict mode script!”;
或在函數內:
function f()
{
//函數範圍內的嚴格模式語法
'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.”; }

在包含這個指令的JavaScript檔案或函式內,我們將一些較大的JavaScript專案中的不良行為直接在JavaScript引擎執行中禁止了。在其他情況中,嚴格模式改變以下的行為:

· 變數只有在前面var 宣告了才能用
· 試圖寫入唯讀屬性所產生的誤差
· 必須用new 關鍵字呼叫建構函式
· this 不會預設指向全域物件
· 非常有限的使用eval()
· 保護保留字元或未來保留字元不被當作變數名稱使用

嚴格模式在新專案中是很有好處的,但是在大多數地方沒有使用到它的舊專案中使用它是非常具有挑戰性的。當你把多個檔案合併到一個檔案時,它也是一個問題,就像可能導致整個檔案都在嚴格模式下執行。
它不是一個聲明,只是一個字面量,早期版本的瀏覽器會忽略它。嚴格模式支援:

· IE 10+
· FF 4+
· Chrome 13+
· Safari 5.1+
· Opera 12+

參閱MDN對於嚴格模式的描述。

20 - 處理一個陣列或單一元素作為參數的方法

相比於寫個單獨的方法去分別操作一個陣列和一個元素作為參數的函數,更好的是寫一個通用的函數,這樣就可以操作。這類似於一些jQuery的方法(css匹配將修改所有的選擇器)。
你只需要先將一切放進數組,Array.concat會接收數組或單一的物件:

function printUpperCase(words) {
var elements = [] .concat(words);
for (var i = 0; i 397e490455325c171ffef9f4ce7495c1 CACTUS
printUpperCase([“cactus”, “ bear”, “potato”]);
// => CACTUS
// BEAR
// POTATO

##21 - undefined 和null 的不同<span style="font-size: 14px;"></span>

· undefined指的是變數未被聲明,或變數被宣告但未賦值· null是指一個特定的值,即」沒有值」
. JavaScript給未賦值的變數預設定義為undefined
· JavaScript不會給未賦值的變數設定null值,它被程式設計師用來表示一個無價值的值
· undefined在json格式資料中是無效的,而null有效
· undefined 類型是undefined
· null類似是object.為什麼呢?
· 兩者都是原始值
· 兩者都被認為是false(Boolean(undefined) // false, Boolean(null) // false)。
· 辨識變數是不是undefined

typeof variable === “undefined” · 檢查變數是不是null

# variable === “null” 從值考慮他們是相等的,但是從類型和值共同考慮他們是不相等的

null == undefined // true null === undefined // false

22 - 以非ASCII字元形式來排序字串<span style="font-size: 14px;"></span>

JavaScript有個原生的方法將字串格式的陣列排序,做一個簡單的array.sort()將會把字串們依照首字母的數序排列。當然,也可以提供自訂排序功能。 <span style="font-size: 14px;"></span>

['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort(); // [“Buenos Aires”, “Mumbai” , “New York”, “Shanghai”]

當你試圖用非ASCII字符,如['é', 'a', 'ú', 'c']這樣的進行排序,你會得到一個奇怪的結果['c', 'e', 'á', 'ú'],因為只有用英語的語言才能排序,所以發生這種情況。 <span style="font-size: 14px;"></span>

看一個簡單的例子:<span style="font-size: 14px;"></span>

// Spanish ['único','árbol', 'cosas', ' fútbol'].sort();
// [“cosas”, “fútbol”, “árbol”, “único”] // 錯誤的排序
// German
['Woche', ' wöchentlich', 'wäre', 'Wann'].sort();
// [“Wann”, “Woche”, “wäre”, “wöchentlich”] // 錯誤的排序

#幸運的是,有兩種方法來避免這種行為,ECMAScript國際化的API提供了localecompare和and Intl.Collat​​or。 這兩種方法都有自己的自訂參數,以便將其配置來充分的完成功能。

使用localeCompare()<span style="font-size: 14px;"></span>

['ú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”]

使用intl.collat​​or()<span style="font-size: 14px;"></span>

['único','árbol ', 'cosas', 'fútbol'].sort(Intl.Collat​​or().compare); // [“árbol”, “cosas”, “fútbol”, “único”]
['Woche ', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collat​​or().compare);
// [“Wann”, “wäre”, “Woche”, “wöchentlich”]

· 每個方法都可以自訂位置<span style="font-size: 14px;"></span>

· 在FF瀏覽器,intl.collat​​or()會比較快,當比較的是較大的數值或字串因此,當你在用英文以外的語言來賦值給字串陣列時,記得要使用此方法來避免意外的排序。

23 - 改善巢狀條件<span style="font-size: 14px;"></span>

我們可以如何改善並且讓JavaScript中的if語句做出更有效的巢狀。 <span style="font-size: 14px;"></span>

if (color) { if (color === 'black') {
printBlackBackground();
} else if (color === ' red') {
printRedBackground();
} else if (color === 'blue') {
printBlueBackground();
} else if (color === 'green') {
printGreenBackground();
} else {
printYellowBackground();
}
}

一個改善的方法是用switch語句取代嵌套的if語句。雖然它是更簡潔,更有序,但不建議這樣做,因為很難debug。這裡指出原因。

switch(color) {
case 'black':
printBlackBackground();
break;
case 'red':
printRedBackground( );
break;
case 'blue':
printBlueBackground();
break;
case 'green':
printGreenBackground();
break;
default:
printYellowBackground();
}

#但是,當我們有多個判斷條件的情況下呢?在這種情況下,如果我們想讓它更加簡潔,更加有序,我們可以使用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;
}

但我們必須避免在每個條件下進行多次檢查,盡量避免使用switch。我們也必須考慮到最有效的方法是透過一個object。
var colorObj = {
'black': printBlackBackground,
'red': printRedBackground,
'blue': printBlueBackground,
'green': printGreenBackground,
'yellows': printYellowBackground
};

if (color in colorObj) {
colorObjcolor;
}

#這裡有更多相關的資訊。

24 - ReactJs 子層級建構的keys是很重要的

keys是代表你需要傳遞給動態陣列的所有元件的一個屬性。這是一個獨特的和指定的ID,react用它來識別每個DOM元件以用來知道這是個不同的元件或是同一個元件。使用keys來確保子元件是可保存的並且不是再次創造的,並且防止怪異事情的產生。

· 使用已存在的一個獨立的物件值
· 定義父元件中的鍵,而不是子元件

/ /不好的

render() {

{{item.name}}

}

//好的

· 使用陣列不是個好習慣
· random()從不會執行
//不好的

· 你可以創建你的唯一id,請確保該方法是快速的並已經附加到對像上的
· 當子級的數量是龐大的或包含複雜的組件,使用keys來提高效能
· 你必須為所有的子級ReactCSSTransitionGroup提供key屬性

#25 - AngularJs: <span style="font-size: 14px;"></span>

<span style="font-size: 14px;"></span>

apply

AngularJs最讓人欣賞的特點是雙向資料綁定。為了是它工作,AngularJs評估模型的變化和視圖的循環(

#digest循環。有時你必須手動運行一個新的循環,你必須有正確的選擇,因為這個階段是效能方面表現出最具影響力的。核心方法讓你來啟動一個

#digest循環。

<span style="font-size: 14px;"></span>

##digest();#############$digest######

在这种情况下,$digest方法在当前作用域和它的子作用域执行,你应该注意到,父级的作用域将不被检查,并没有受到影响。
建议:

· 只在浏览器DOM事件在Angular之外被触发的时候使用

digest
· 给$apply传递函数表达式,这有一个错误处理机制,允许在消化周期中整合变化。

apply(() => {
$scope.tip = ‘Javascript Tip’;
});

· 如果你仅仅想更新当前作用域或者他的子作用域,用

digest。性能不言而喻咯。
· 当

evalAsync。这是一个在当前循环或下一次循环的期间或对表达式做出评估的核心方法,这可以提高你的应用程序的性能。

25 - 在数组插入一个项

将一个项插入到现有数组中,是一个日常常见的任务,你可以使用push在数组的末尾添加元素,使用unshift在开始的位置,或者在中间使用splice。

这些都是已知的方法,但这并不意味着没有一个更高性能的途径。我们来看一看。
在数组的末尾添加一个元素很容易与push(),但还有一个更高性能的途径。
var arr = [1,2,3,4,5];
arr.push(6);
arr[arr.length] = 6; //在Chrome 47.0.2526.106 (Mac OS X 10.11.1)上提高了 43% 的速度

这两种方法都修改了数组,不相信我?看这个jsperf
现在,如果我们正在尝试将一个项目添加到数组的开头:

var arr = [1,2,3,4,5];
arr.unshift(0);
[0].concat(arr); //在Chrome 47.0.2526.106 (Mac OS X 10.11.1)上提高了 98% 的速度

这里更详细一点:unshift编辑原有的数组,concat返回一个新数组。jsperf
添加在阵列中的物品很容易使用splice,它是做它的最高效的方式。
?
1
2

var items = [‘one’, ‘two’, ‘three’, ‘four’];
items.splice(items.length / 2, 0, ‘hello’);

我试着在不同的浏览器和操作系统中运行这些测试,结果是相似的。我希望这些建议对你有用,鼓励你自己做测试!

1、javascript 容错处理代码(屏蔽js错误)

<span style="font-size: 14px;"><script language="javascript"><br/>    <!--    /*屏蔽所有的js错误*/<br/>    function killerrors() {<br/>        return true;<br/>    }<br/>    window.onerror = killerrors;    //--></script><br/></span>

能够为大家提供这些简短而实用的JavaScript技巧来提高大家编程能力,这对于我来说是件很开心的事。每天仅花上不到2分钟的时间中,你将可以读遍JavaScript这门可怕的语言所呈现给我们的特性:performance(性能), conventions(协议), hacks(代码hack), interview questions(面试问题)及所有其他的项。

2、 使用 === 代替 ==

==(或者!=)做对比的时候会将进行对比的两者转换到同一类型再比较。===(或者!==)则不会,他会将进行对比的两者做类型对比和值对比,相对于 == ,=== 的对比会更加严谨。
[10] == 10 // true
[10] === 10 // false
“10” == 10 // true
“10” === 10 // false
[] == 0 // true
[] === 0 // false
“” == false // true 但是 true == “a” 是false
“” === false // false

3、转换数值的更加的方法

将字符串转换为数字是非常常见的。最简单和最快的(jspref)的方式来实现,将使用+(加)算法。

var one = ‘1’;
var numberOne = +one; // Number 1

你也可以使用-(減號)演算法的轉換類型並且變成負數值。

var one = '1';
var negativeNumberOne = -one; // Number -1

##4 - 清除一個陣列<span style="font-size: 14px;"></span>

你定義一個數組,並且希望清空它的內容。通常,你會這樣做:<span style="font-size: 14px;"></span>

var list = [1, 2, 3, 4]; function empty() {
//清空陣列
list = [];
}
empty();

但是還有一個更高效能的方法。 <span style="font-size: 14px;"></span>

你可以使用這些程式碼: var list = [1, 2, 3, 4];
function empty() {
//清空陣列
list.length = 0;
}
empty();

· list =[] 指定一個變數引用到那個數組,而其他引用都不受影響。這意味著,對於先前數組的內容的引用仍然保留在記憶體中,從而導致記憶體洩漏。 · list.length = 0 刪除數組內的所有東西,這不需要引用任何其他的東西
然而,如果你有一個copy的數組(A和copy-A),如果你使用list.length = 0 刪除其內容,副本也會失去它的內容。
var foo = [1,2,3];
var bar = [1,2,3];
var foo2 = foo;
var bar2 = bar;
foo = [ ];
bar.length = 0;
console.log(foo, bar, foo2, bar2);
//[] [] [1, 2, 3] []

StackOverflow上的更多詳情:difference-between-array-length-0-and-array<span style="font-size: 14px;"></span>

5 - 對陣列排序進行」洗牌」(隨機排序)<span style="font-size: 14px;"></span>

這段程式碼在這裡使用Fisher Yates洗牌演算法給一個指定的陣列進行洗牌(隨機排序)。 function shuffle(arr) {
var i,
j,
temp;
for (i = arr.length - 1; i > 0; i–) {
j = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;  
};

# 案例: ?
1
2
3
4

var a = [1, 2, 3, 4, 5, 6, 7, 8]; var b = shuffle(a);
console. log(b);
// [2, 7, 8, 6, 5, 3, 1, 4]

6 - 傳回物件的函數能夠用於鍊式操作<span style="font-size: 14px;"></span>

當建立物件導向的JavaScript物件的function時,函數傳回一個物件將能夠讓函數可鍊式的寫在一起來執行。 <span style="font-size: 14px;"></span>

function Person(name) { this.name = name;
this.sayName = function() {
console.log(“Hello my name is : “, this.name);
return this;
};
this.changeName = function(name) {
this.name = name;
return this;
} ;
}
var person = new Person(“John”);
person.sayName().changeName(“Timmy”).sayName();
//Hello my name is: John
//Hello my name is: Timmy

7 - 字串安全連線<span style="font-size: 14px;"></span>

假設你有一些類型未知的變量,你想將它們連接起來。可以肯定的是,演算法操作不會在級聯時應用:<span style="font-size: 14px;"></span>

var one = 1; var two = 2;
var three = '3';
var result = ”.concat(one, two, three); //”123”

這樣的連接不正是你所期望的。相反,一些串聯和相加可能會導致意想不到的結果:<span style="font-size: 14px;"></span>

var one = 1; var two = 2;
var three = '3';
var result = one + two + three; //”33” 而不是“123”

談到性能,對join和concat進行比較,他們的執行速度是幾乎一樣的。在MDN了解更多與concat相關的知識<span style="font-size: 14px;"></span>

8 - 更快的四捨五入<span style="font-size: 14px;"></span>

今天的技巧是關於性能。雙波浪線”~~”操作符嗎?位元轉換輸入-(輸入+1),因此雙位移將輸入轉換為-(-(輸入+1)),這是一個趨於0的偉大的工具。取負值和Math.floor()取正值。

// 單一位移
console.log(~1337) // -1338
// 雙移
console.log(47.11) // -> 47
console.log(
-12.88) // -> -12
console.log(1.9999) // -> 1
console.log(~~3) // -> 3
//失敗的情況
console.log(
[]) // -> 0  
console.log(NaN) // -> 0
console.log(~~null) // -> 0
//大於32位元整數則失敗
console.log(
(2147483647 + 1) === (2147483647 + 1) ) // -> 0

雖然~~可能有更好的表現,為了可讀性,請使用Math.floor()。

9 - Node.js:讓module在沒被require的時候運行

在node裡,你可以根據代是運行了require('./something.js')還是node something.js,來告訴你的程式去做兩件不同的事情。如果你想與你的一個獨立的模組進行交互,這是很有用的。

if (!module.parent) {
// 執行
<span style="font-size: 14px;">node something.js</span>
#app.listen(8088, function() {
console.log('app listening on port 8088');
})
} else {
// 使用
<span style="font-size: 14px;">#require('/.something.js')</span>
module.exports = app;
}

更多信息,請看the documentation for modules

10 - 給回調函數傳遞參數

在預設情況下,你無法將參數傳給回調函數,如下:

function callback() {
console.log('Hi human');
}
document.getElementById('someelem'). addEventListener('click', callback);

你可以取JavaScript閉包的優點來給予回呼函數傳參,案例如下:

function callback(a, b) {
return function() {
console.log('sum = ', (a+b));
}
}
var x = 1, y = 2;
document.getElementById('someelem').addEventListener('click', callback(x, y));

#什麼是閉包呢?閉包是指一個針對獨立的(自由)變數的函數。換句話說,閉包中定義的函數會記住它被創造的環境。了解更多請參閱MDN所以這種方式當被呼叫的時候,參數X/Y存在於回呼函數的作用域內。

另一種方法是使用綁定方法。例如:

var alertText = function(text) {
alert(text);
};
document.getElementById('someelem').addEventListener(' click', alertText.bind(this, 'hello'));

#兩種方法在效能上有一些略微區別,詳情請參閱jsperf

<span style="font-size: 14px;"></span>

<span style="font-size: 14px;"></span>






<span style="font-size: 14px;"></span>

##11 - 使用更簡單的類似indexOf的包含判斷方式



原生的JavaScript沒有contains方法。對檢查字串或字串陣列項目中是否存在某值,你可以這樣做:

    var someText = 'JavaScript rules';
  • if (someText.indexOf(' JavaScript') !== -1) {

    } // 或if (someText.indexOf('JavaScript') >= 0) {

    }
  • 但是我們再看看這些ExpressJs程式碼片段。

  • // examples/mvc/lib/boot.js

    for (var key in obj) { // “reserved” exports if (~[ 'name', 'prefix', 'engine', 'before'].indexOf(key)) continue;

  • <span style="font-size: 14px;"></span>// examples/lib/utils. js


  • exports.normalizeType = function(type){

##return ~type. indexOf('/')

? acceptParams(type)

#####{ value: mime.lookup(type), params: {} }; ###};###################// examples/web-service/index.js ### // key is invalid ###if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key'));#############問題是~位運算符。 「運算子執行操作這樣的二進位表達式,但他們傳回標準的JavaScript的數值。」###他們將-1轉換為0,而0在JavaScript中又是false。 ######

var someText = 'text';
!!~someText.indexOf('tex'); // someText 包含「tex」 - true
!~someText.indexOf('tex') ; // someText 不包含「tex」 - false
~someText.indexOf('asd'); // someText 不包含「asd」 - false
~someText.indexOf('ext'); // someText包含「ext」 - true
String.prototype.includes()

在ES6(ES 2015)中介紹了includes()方法可以用來決定是否一個字串包含另一個字串:

'something'.includes('thing'); // true

##在ECMAScript 2016 (ES7)中,甚至連陣列都可以這樣操作,如indexOf:<span style="font-size: 14px;"></span>

!!~[1, 2, 3].indexOf(1); // true [1, 2, 3].includes(1); // true

不幸的是,這只是在Chrome,Firefox,Safari 9或以上的瀏覽器中被支援。 <span style="font-size: 14px;"></span>

12 - arrow 函數(ES6)<span style="font-size: 14px;"></span>

#介紹下ES6裡的新功能,arrow函數可能會是個很方便的工具,用更少行數寫更多程式碼。他的名字來自他的語法,=>和小箭頭->比就像一個“胖胖的箭頭”。或許有些人知道,這種函數型別和其他靜態語言如lambda表達式的匿名函數。它被稱為匿名,因為這些箭頭函數沒有一個描述性的函數名。 那麼這樣有什麼好處呢?

語法:更少的LOC,不用一次次的鍵入函數關鍵字。 <span style="font-size: 14px;"></span>

語意:從上下文中捕捉關鍵字this。 <span style="font-size: 14px;"></span>

簡單語法案例:<span style="font-size: 14px;"></span>

看看下面的兩段程式碼片段,他們做的是一樣的工作。你能很快的理解arrow函數的功能。 <span style="font-size: 14px;"></span>

// arrow函數的日常語法param => expression
// 可能也會寫在括號中
// 括號是多參數需求
(param1 [, param2]) => expression

// 使用日常函數var arr = [5,3,2,9,1];
var arrFunc = arr.map(function(x) {
return x * x;
});
console.log(arr)

//使用arrow函數var arr = [5,3,2,9,1];
var arrFunc = arr.map((x) => x*x);
console.log(arr )

如你所看到的,這個例子中的arrow函數可以節省你輸入括號內參數和回傳關鍵字的時間。建議把圓括號內的參數輸入,如 (x,y) => x+y 。在不同的使用情況下,它只是<span style="font-size: 14px;"></span>

用來應對遺忘的一種方式。但是上面的程式碼也會這樣執行:x => x*x.目前看來,這些僅僅是導致更少的LOC和更好的可讀性的句法改進。 <span style="font-size: 14px;"></span>

this 綁定<span style="font-size: 14px;"></span>

還有一個更好的理由使用arrow函數。那就是在會出現this問題的背景下。使用arrow函數,你就不用擔心.bind(this)和 that=this 了。因為arrow函數會從上下文找到this。 <span style="font-size: 14px;"></span>

看下面的範例:<span style="font-size: 14px;"></span>

// 全域定義this.i this.i = 100;
var counterA = new CounterA();
var counterB = new CounterB();
var counterC = new CounterC();
var counterD = new CounterD();



<span style="font-size: 14px;"></span>


<span style="font-size: 14px;"></span><span style="font-size: 14px;"></span><span style="font-size: 14px;"></span>





























################################################### # #// 不好的範例###function CounterA() { ###// CounterA's #########this######### 實例(!! 忽略這裡) ### this.i = 0; ###setInterval(function () { ###// ##########this######### 指全域對象,而不是CounterA's #### #####this###### ######// 因此,開始計數與100,而不是0 (本地的this.i) ###this.i++; ###document.getElementById (“counterA”).innerHTML = this.i; ###}, 500); ###} ###// 手動綁定that = this ###function CounterB() { ###this.i = 0; ###var that = this; ###setInterval(function() { ###that.i++; ###document.getElementById(“counterB”).innerHTML = that.i; ###}, 500 ); ###} ###// 使用.bind(this) ###function CounterC() { ###this.i = 0; ###setInterval(function() { ###this.i++; ###document.getElementById(“counterC”).innerHTML = this.i; ###}.bind(this), 500); ###} ###// 使用arrow函數###function CounterD() { ###this.i = 0; ###setInterval(() => { ###this.i++; ###document.getElementById(“counterD”).innerHTML = this.i; ###} , 500); ###}######

關於arrow函數的進一步資訊可以看這裡 。查看不同的語法選請造訪該網站。

13 - 測量一個JavaScript程式碼區塊效能的技巧

#快速測量一個JavaScript區塊的效能,我們可以使用控制台的功能像console.time(label)和console.timeEnd(label)

console.time(“Array initialize”);
var arr = new Array(100),
len = arr.length,
i;
for (i = 0; i 071589045ef92c31c77214327054c338 a + b
getSum( 10 ) // throws Error, b is not defined
getSum( undefined, 10 ) // throws Error , a is not defined

_err是立即拋出一個錯誤的函數。如果沒有一個參數作為值,預設值是會被使用,_err會被調用,將會拋出錯誤。你可以在Mozilla開發者網路看到的更多預設參數的例子。

15 - 提升

理解提升將幫助你組織你的function。只需要記住,變數宣告和定義函數會被提升到頂部。變數的定義是不會的,即使你在同一行中宣告和定義一個變數。此外,變數宣告讓系統知道變數存在,而定義是將其賦值給它。

function doTheThing() {
// 錯誤: notDeclared is not defined
console.log(notDeclared);
// 輸出: undefined
console .log(definedLater);
var definedLater;
definedLater = 'I am defined!'
// 輸出: 'I am defined!'
console.log(definedLater)
// Outputs: undefined
console.log(definedSimulateneously);
var definedSimulateneously = 'I am defined!'
// 輸出: 'I am defined!'
console.log(definedSimulateneously) ##defconsole.log(definedSimulateneously) ##。 // 輸出: 'I did it!'
doSomethingElse();
function doSomethingElse(){
console.log('I did it!');
}
// 錯誤: undefined is not a function
functionVar();
var functionVar = function(){
console.log('I did it!');
}
}

為了讓事情更容易閱讀,在函數作用域內提升變數的宣告會讓你明確該變數的宣告是來自哪個作用域。在你需要使用變數之前定義它們。在作用域底部定義函數,確保程式碼清晰規範。 <span style="font-size: 14px;"></span>

16 - 檢查一個物件是否有屬性<span style="font-size: 14px;"></span>

#當你要檢查一個物件是否存在某個屬性時,你可能會這樣做:<span style="font-size: 14px;"></span>

var myObject = { name: '@tips_js'
};
if (myObject.name) { … }

#這是可以的,但你必須知道這個還有兩原生的方式,in operator 和object.hasownproperty,每個物件是對象,既可用方法。每個object都繼承自Object,這兩個方法都可用。 <span style="font-size: 14px;"></span>

兩個方法的一些不同點:<span style="font-size: 14px;"></span>

#var myObject = { name: '@tips_js'
};
myObject.hasOwnProperty('name'); // true
'name' in myObject; // true
myObject.hasOwnProperty('valueOf'); // false, valueOf 是從原型鏈繼承的
'valueOf' in myObject; // true

他們之間的不同在於檢查的性質,換句話說,當該物件本身有查找的屬性時hasOwnProperty傳回yrue ,然而,in operator不區分屬性創建的物件和屬性繼承的原型鏈。 這裡有另一個例子:

var myFunc = function() { this.name = '@tips_js';
};
myFunc. prototype.age = '10 days';
var user = new myFunc();
user.hasOwnProperty('name'); // true
user.hasOwnProperty('age'); // false , 因為age是原型鏈上的
#

点击看例子。同时,建议在检查对象的属性存在时,阅读这些有关的常见错误。

17 - 模板字符串

截至ES6,JS已经有模板字符串作为替代经典的结束引用的字符串。
案例:普通字符串

var firstName = ‘Jake’;
var lastName = ‘Rawr’;
console.log(‘My name is ’ + firstName + ’ ’ + lastName);
// My name is Jake Rawr  
模板字符串:
var firstName = ‘Jake’;
var lastName = ‘Rawr’;
console.log(
<span style="font-size: 14px;">My name is ${firstName} ${lastName}</span>);
// My name is Jake Rawr

在模板字符串中${}中,你可以写不用写/n或者简单逻辑来实现多行字符串。
您还可以使用函数来修改模板字符串的输出,它们被称为模板字符串的标记。你可能还想读到更多的理解模板字符串相关信息。

18- 將節點清單轉換為陣列

querySelectorAll 方法傳回一個和陣列類似的節點列表物件。這些資料結構類似數組,因為常以數組形式出現,但是又不能用數組的方法,例如map和foreach。這裡是一個快速、安全、可重複使用的方式將一個節點列表到一個DOM元素數組:

const nodelist = document.querySelectorAll('p');
const nodelistToArray = Array.apply(null, nodelist);
//later on ..
nodelistToArray.forEach(…);
nodelistToArray.map(…);
nodelistToArray.slice(…);
//etc…

apply方法是將一系列陣列格式的參數傳遞給一個給定this的函數。 MDN指出,apply將會呼叫類似陣列的對象,而這正是querySelectorAll所傳回的。因為我們不需要在函數的上下文中指定this,所以我們傳入null或0。傳回的結果是一組能使用陣列方法的DOM元素數組。

如果你使用的是es2015可以利用…(spread operator)

const nodelist = […document.querySelectorAll('p') ]; // 回傳的是個真實的陣列
//later on ..
nodelist.forEach(…);
nodelist.map(…);
nodelist.slice(…);
//etc…

19 - “use strict” 和懶惰

嚴格模式的JavaScript讓開發人員更安全的編寫JavaScript 。
預設情況下,JavaScript允許開發者懶惰,例如,我們在第一次宣告變數的時候可以不用var,雖然這可能看起來像一個沒有經驗的開發人員,同時這也是很多錯誤的根源,變數名拼字錯誤或意外地將它提到了外部作用域。

程式設計師喜歡讓電腦為我們做些無聊的事,檢查一些我們工作的錯誤。 「use strict」指令我們來做這些,將我們的錯誤轉換成JavaScript的錯誤。

我們把這個指令可以透過加在一個js檔案的頂部:

// 整個script檔都會是嚴格模式語法
“use strict”;
var v = “Hi! I'm a strict mode script!”;
或在函數內:
function f()
{
//函數範圍內的嚴格模式語法
'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.”; }

在包含這個指令的JavaScript檔案或函式內,我們將一些較大的JavaScript專案中的不良行為直接在JavaScript引擎執行中禁止了。在其他情況中,嚴格模式改變以下的行為:

· 變數只有在前面var 宣告了才能用
· 試圖寫入唯讀屬性所產生的誤差
· 必須用new 關鍵字呼叫建構函式
· this 不會預設指向全域物件
· 非常有限的使用eval()
· 保護保留字元或未來保留字元不被當作變數名稱使用

嚴格模式在新專案中是很有好處的,但是在大多數地方沒有使用到它的舊專案中使用它是非常具有挑戰性的。當你把多個檔案合併到一個檔案時,它也是一個問題,就像可能導致整個檔案都在嚴格模式下執行。
它不是一個聲明,只是一個字面量,早期版本的瀏覽器會忽略它。嚴格模式支援:

· IE 10+
· FF 4+
· Chrome 13+
· Safari 5.1+
· Opera 12+

參閱MDN對於嚴格模式的描述。

20 - 處理一個陣列或單一元素作為參數的方法

相比於寫個單獨的方法去分別操作一個陣列和一個元素作為參數的函數,更好的是寫一個通用的函數,這樣就可以操作。這類似於一些jQuery的方法(css匹配將修改所有的選擇器)。
你只需要先將一切放進數組,Array.concat會接收數組或單一的物件:

function printUpperCase(words) {
var elements = [] .concat(words);
for (var i = 0; i 397e490455325c171ffef9f4ce7495c1 CACTUS
printUpperCase([“cactus”, “ bear”, “potato”]);
// => CACTUS
// BEAR
// POTATO

##21 - undefined 和null 的不同<span style="font-size: 14px;"></span>

· undefined指的是變數未被聲明,或變數被宣告但未賦值· null是指一個特定的值,即」沒有值」
. JavaScript給未賦值的變數預設定義為undefined
· JavaScript不會給未賦值的變數設定null值,它被程式設計師用來表示一個無價值的值
· undefined在json格式資料中是無效的,而null有效
· undefined 類型是undefined
· null類似是object.為什麼呢?
· 兩者都是原始值
· 兩者都被認為是false(Boolean(undefined) // false, Boolean(null) // false)。
· 辨識變數是不是undefined

typeof variable === “undefined” · 檢查變數是不是null

# variable === “null” 從值考慮他們是相等的,但是從類型和值共同考慮他們是不相等的

null == undefined // true null === undefined // false

22 - 以非ASCII字元形式來排序字串<span style="font-size: 14px;"></span>

JavaScript有個原生的方法將字串格式的陣列排序,做一個簡單的array.sort()將會把字串們依照首字母的數序排列。當然,也可以提供自訂排序功能。 <span style="font-size: 14px;"></span>

['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort(); // [“Buenos Aires”, “Mumbai” , “New York”, “Shanghai”]

當你試圖用非ASCII字符,如['é', 'a', 'ú', 'c']這樣的進行排序,你會得到一個奇怪的結果['c', 'e', 'á', 'ú'],因為只有用英語的語言才能排序,所以發生這種情況。 <span style="font-size: 14px;"></span>

看一個簡單的例子:<span style="font-size: 14px;"></span>

// Spanish ['único','árbol', 'cosas', ' fútbol'].sort();
// [“cosas”, “fútbol”, “árbol”, “único”] // 錯誤的排序
// German
['Woche', ' wöchentlich', 'wäre', 'Wann'].sort();
// [“Wann”, “Woche”, “wäre”, “wöchentlich”] // 錯誤的排序

#幸運的是,有兩種方法來避免這種行為,ECMAScript國際化的API提供了localecompare和and Intl.Collat​​or。 這兩種方法都有自己的自訂參數,以便將其配置來充分的完成功能。

使用localeCompare()<span style="font-size: 14px;"></span>

['ú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”]

使用intl.collat​​or()<span style="font-size: 14px;"></span>

['único','árbol ', 'cosas', 'fútbol'].sort(Intl.Collat​​or().compare); // [“árbol”, “cosas”, “fútbol”, “único”]
['Woche ', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collat​​or().compare);
// [“Wann”, “wäre”, “Woche”, “wöchentlich”]

· 每個方法都可以自訂位置<span style="font-size: 14px;"></span>

· 在FF瀏覽器,intl.collat​​or()會比較快,當比較的是較大的數值或字串因此,當你在用英文以外的語言來賦值給字串陣列時,記得要使用此方法來避免意外的排序。

23 - 改善巢狀條件<span style="font-size: 14px;"></span>

我們可以如何改善並且讓JavaScript中的if語句做出更有效的巢狀。 <span style="font-size: 14px;"></span>

if (color) { if (color === 'black') {
printBlackBackground();
} else if (color === ' red') {
printRedBackground();
} else if (color === 'blue') {
printBlueBackground();
} else if (color === 'green') {
printGreenBackground();
} else {
printYellowBackground();
}
}

一個改善的方法是用switch語句取代嵌套的if語句。雖然它是更簡潔,更有序,但不建議這樣做,因為很難debug。這裡指出原因。

switch(color) {
case 'black':
printBlackBackground();
break;
case 'red':
printRedBackground( );
break;
case 'blue':
printBlueBackground();
break;
case 'green':
printGreenBackground();
break;
default:
printYellowBackground();
}

#但是,當我們有多個判斷條件的情況下呢?在這種情況下,如果我們想讓它更加簡潔,更加有序,我們可以使用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;
}

但我們必須避免在每個條件下進行多次檢查,盡量避免使用switch。我們也必須考慮到最有效的方法是透過一個object。
var colorObj = {
'black': printBlackBackground,
'red': printRedBackground,
'blue': printBlueBackground,
'green': printGreenBackground,
'yellows': printYellowBackground
};

if (color in colorObj) {
colorObjcolor;
}

#這裡有更多相關的資訊。

24 - ReactJs 子層級建構的keys是很重要的

keys是代表你需要傳遞給動態陣列的所有元件的一個屬性。這是一個獨特的和指定的ID,react用它來識別每個DOM元件以用來知道這是個不同的元件或是同一個元件。使用keys來確保子元件是可保存的並且不是再次創造的,並且防止怪異事情的產生。

· 使用已存在的一個獨立的物件值
· 定義父元件中的鍵,而不是子元件

/ /不好的

render() {

{{item.name}}

}

//好的

· 使用陣列不是個好習慣
· random()從不會執行
//不好的

· 你可以創建你的唯一id,請確保該方法是快速的並已經附加到對像上的
· 當子級的數量是龐大的或包含複雜的組件,使用keys來提高效能
· 你必須為所有的子級ReactCSSTransitionGroup提供key屬性

#25 - AngularJs: <span style="font-size: 14px;"></span>

<span style="font-size: 14px;"></span>

apply

AngularJs最讓人欣賞的特點是雙向資料綁定。為了是它工作,AngularJs評估模型的變化和視圖的循環(

#digest循環。有時你必須手動運行一個新的循環,你必須有正確的選擇,因為這個階段是效能方面表現出最具影響力的。核心方法讓你來啟動一個

#digest循環。

<span style="font-size: 14px;"></span>

##digest();#############$digest######

在这种情况下,$digest方法在当前作用域和它的子作用域执行,你应该注意到,父级的作用域将不被检查,并没有受到影响。
建议:

· 只在浏览器DOM事件在Angular之外被触发的时候使用

digest
· 给$apply传递函数表达式,这有一个错误处理机制,允许在消化周期中整合变化。

apply(() => {
$scope.tip = ‘Javascript Tip’;
});

· 如果你仅仅想更新当前作用域或者他的子作用域,用

digest。性能不言而喻咯。
· 当

evalAsync。这是一个在当前循环或下一次循环的期间或对表达式做出评估的核心方法,这可以提高你的应用程序的性能。

25 - 在数组插入一个项

将一个项插入到现有数组中,是一个日常常见的任务,你可以使用push在数组的末尾添加元素,使用unshift在开始的位置,或者在中间使用splice。

这些都是已知的方法,但这并不意味着没有一个更高性能的途径。我们来看一看。
在数组的末尾添加一个元素很容易与push(),但还有一个更高性能的途径。
var arr = [1,2,3,4,5];
arr.push(6);
arr[arr.length] = 6; //在Chrome 47.0.2526.106 (Mac OS X 10.11.1)上提高了 43% 的速度

这两种方法都修改了数组,不相信我?看这个jsperf
现在,如果我们正在尝试将一个项目添加到数组的开头:

var arr = [1,2,3,4,5];
arr.unshift(0);
[0].concat(arr); //在Chrome 47.0.2526.106 (Mac OS X 10.11.1)上提高了 98% 的速度

这里更详细一点:unshift编辑原有的数组,concat返回一个新数组。jsperf
添加在阵列中的物品很容易使用splice,它是做它的最高效的方式。
?
1
2

var items = [‘one’, ‘two’, ‘three’, ‘four’];
items.splice(items.length / 2, 0, ‘hello’);

我试着在不同的浏览器和操作系统中运行这些测试,结果是相似的。我希望这些建议对你有用,鼓励你自己做测试!

以上是js一些小技巧分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn