2018-01-05 arrow 函數(ES6)、測量一個JavaScript代碼塊性能的技巧立磁、ES6中參數處理呈队、提升、檢查一個對象是否有屬性唱歧、模板字符串宪摧、將節(jié)點列表轉換為數組

1 給回調函數傳遞參數

在默認情況下,你無法將參數傳給回調函數颅崩,如下:

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

你可以采取JavaScript閉包的優(yōu)點來給回調函數傳參绍刮,案例如下:

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

什么是閉包呢?閉包是指一個針對獨立的(自由)變量的函數挨摸。換句話說孩革,閉包中定義的函數會記住它被創(chuàng)建的環(huán)境。了解更多請參閱MDN所以這種方式當被調用的時候得运,參數X/Y存在于回調函數的作用域內膝蜈。
另一種方法是使用綁定方法。例如:

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

兩種方法在性能上有一些略微區(qū)別熔掺,詳情參閱jsperf

2 使用更簡單的類似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;
 
// 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'));

問題是~位運算符推沸。"運算符執(zhí)行操作這樣的二進制表達式,但他們返回標準的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:
!!~[1, 2, 3].indexOf(1); // true
[1, 2, 3].includes(1); // true
不幸的是宇驾,這只是在Chrome倍靡,Firefox,Safari 9或以上的瀏覽器中被支持课舍。

3 arrow 函數(ES6)

介紹下ES6里的新功能塌西,arrow函數可能會是個很方便的工具,用更少行數寫更多代碼筝尾。他的名字來源于他的語法捡需,=>和小箭頭->比就像一個“胖胖的箭頭”〕镆可能有些人知道栖忠,這種函數類型和其他靜態(tài)語言如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)

正如你所看到的娇跟,這個例子中的arrow函數可以節(jié)省你輸入括號內參數和返回關鍵字的時間岩齿。建議把圓括號內的參數輸入,如 (x,y) => x+y 苞俘。在不同的使用情況下盹沈,它只是用來應對遺忘的一種方式。但是上面的代碼也會這樣執(zhí)行: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);
}
4 測量一個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
5 ES6中參數處理

在許多編程語言中吧碾,函數的參數是默認的,而開發(fā)人員必須顯式定義一個參數是可選的飞蚓。在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開發(fā)者網絡看到的更多默認參數的例子屁倔。

6 提升

理解提升將幫助你組織你的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!');
}
}

為了使事情更容易閱讀布轿,在函數作用域內提升變量的聲明將會讓你明確該變量的聲明是來自哪個作用域哮笆。在你需要使用變量之前定義它們。在作用域底部定義函數汰扭,確保代碼清晰規(guī)范稠肘。

7 檢查一個對象是否有屬性

當你要檢查一個對象是否存在某個屬性時,你可能會這樣做 :

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不區(qū)分屬性創(chuàng)建的對象和屬性繼承的原型鏈。

這里有另外一個例子:

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是原型鏈上的
8 模板字符串

截至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(`My name is ${firstName} ${lastName}`);
// My name is Jake Rawr

在模板字符串中${}中帝嗡,你可以寫不用寫/n或者簡單邏輯來實現多行字符串。

您還可以使用函數來修改模板字符串的輸出璃氢,它們被稱為模板字符串的標記哟玷。你可能還想讀到更多的理解模板字符串相關信息。

9 將節(jié)點列表轉換為數組

querySelectorAll 方法返回一個和數組類似的節(jié)點列表對象一也。這些數據結構類似數組巢寡,因為經常以數組形式出現,但是又不能用數組的方法椰苟,比如map和foreach抑月。這里是一個快速、安全舆蝴、可重用的方式將一個節(jié)點列表到一個DOM元素數組:

const nodelist = document.querySelectorAll('div');
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('div')]; // 返回的是個真實的數組
//later on ..
nodelist.forEach(...);
nodelist.map(...);
nodelist.slice(...);
//etc...
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市祭椰,隨后出現的幾起案子臭家,更是在濱河造成了極大的恐慌,老刑警劉巖方淤,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钉赁,死亡現場離奇詭異,居然都是意外死亡携茂,警方通過查閱死者的電腦和手機你踩,發(fā)現死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讳苦,“玉大人带膜,你說我怎么就攤上這事≡眨” “怎么了膝藕?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咐扭。 經常有香客問我芭挽,道長滑废,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任袜爪,我火速辦了婚禮蠕趁,結果婚禮上,老公的妹妹穿的比我還像新娘辛馆。我一直安慰自己俺陋,他們只是感情好,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布昙篙。 她就那樣靜靜地躺著腊状,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瓢对。 梳的紋絲不亂的頭發(fā)上寿酌,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天胰苏,我揣著相機與錄音硕蛹,去河邊找鬼。 笑死硕并,一個胖子當著我的面吹牛法焰,可吹牛的內容都是我干的。 我是一名探鬼主播倔毙,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼埃仪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陕赃?” 一聲冷哼從身側響起卵蛉,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎么库,沒想到半個月后傻丝,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡诉儒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年葡缰,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忱反。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡泛释,死狀恐怖,靈堂內的尸體忽然破棺而出温算,到底是詐尸還是另有隱情怜校,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布注竿,位于F島的核電站茄茁,受9級特大地震影響宇智,放射性物質發(fā)生泄漏。R本人自食惡果不足惜胰丁,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一随橘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锦庸,春花似錦机蔗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扬卷,卻和暖如春牙言,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怪得。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工咱枉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人徒恋。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓蚕断,卻偏偏與公主長得像,于是被迫代替她去往敵國和親入挣。 傳聞我的和親對象是個殘疾皇子亿乳,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內容

  • 第5章 引用類型(返回首頁) 本章內容 使用對象 創(chuàng)建并操作數組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,219評論 0 4
  • 三,字符串擴展 3.1 Unicode表示法 ES6 做出了改進径筏,只要將碼點放入大括號葛假,就能正確解讀該字符。有了這...
    eastbaby閱讀 1,521評論 0 8
  • [TOC] 參考阮一峰的ECMAScript 6 入門參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,773評論 0 1
  • 可能總有人愿意對別人評頭論足指指點點魔眨,可是人干不干凈,難道真的只是靠會說話的一張嘴嗎酿雪?你要是這樣覺得遏暴,我只想和你說...
    GDragon信仰閱讀 414評論 0 0
  • 我的生命有什么可能朋凉?古典 我們的生命到底有什么可能?多少種追尋方向醋安?這些追尋之間到底誰優(yōu)誰劣杂彭? 追尋改變世界的人墓毒,...
    一枚冰兒閱讀 238評論 2 0