摘要:在閱讀的過程中,發現了它的一些小技巧,對我們平時的編程很有用。事實上,在上也的確是可以被更改的而在或高版本的中,并不能更改全局的。但是,局部的仍然可以被改變。所以,建議在已知長度的情況下,使用第一種,而不知道長度的情況下,使用第二種。
在閱讀 underscore 的過程中,發現了它的一些小技巧,對我們平時的編程很有用。在這里向大家介紹一二
void 0 代替 underfined首先,看源碼:
_.isUndefined = function(obj) { return obj === void 0; };
這里為啥要用 obj === void 0, 而不是 obj === undefined 呢?
因為,在 js 中,undefined 并不是類似關鍵字(js 關鍵字有 function,return ...),所以,理論上是可以更改的。
事實上,在 IE8 上也的確是可以被更改的,
var undefined = 1; alert(undefined); // 1 -- IE8, undefined --- chrome
而在 chrome 或高版本的 IE 中,并不能更改全局的 undefined 。但是,局部的 undefined 仍然可以被改變。例如:
(function() { var undefined = 1; alert(undefined); // 1 -- chrome })();
所以, undefined 并不十分可靠,所以才需要 void 0 , void 是 js 的保留字,所以不可被更改。
在 MDN 上定義是:The void operator evaluates the given expression and then returns undefined.
翻譯:void 操作符會對 void 后面的表達式進行運算,然后返回 undefined
所以,使用void會一直返回 undefined ,所以,可以用void 0替代undefined.
復制數組Array.prototype.slice.call(array); 可用來復制一個數組,或將類數組轉換為數組
在 js 中,如果我們想復制一個數組,要如何復制呢?也許你會這樣做:
function copy(array) { var copyArray = []; for (var i = 0, len = array.length; i < len; i++) { copyArray.push(array[i]); } return copyArray; }
其實,我們可以利用數組的 slice 和 concat 方法返回新的數組這個特性,來實現復制數組的功能;
var newArray = Array.prototype.slice.call(array); var newArray2 = Array.prototype.concat.call(array);
而且,性能方面, slice 以及 concat 比單純使用 for 循環還要更加高效
var array = _.range(10000000); //_.range,是undescore一個方法,用于生成一個從0到10000000的數組 console.time("for copy push"); var copyArray1 = []; for (var i = 0, length = array.length; i < length; i++) { copyArray1.push(array[i]); } console.timeEnd("for copy push"); console.time("slice"); var copyArray2 = Array.prototype.slice.call(array); console.timeEnd("slice"); console.time("concat"); var copyArray3 = Array.prototype.concat.call(array); console.timeEnd("concat"); //結果 //for copy push: 379.315ms //slice: 109.300ms //concat: 92.852ms
另外,也是通過 slice , call 將類數組轉換為數組
function test() { console.log(Array.prototype.slice.call(arguments)); } test(1, 2, 3); //輸出[1, 2, 3]使用 Array[length]=value 代替 push 添加元素
實際業務代碼,除非對性能要求極高,否則還是推薦 push,畢竟更符合習慣
首先看源碼 _.values()
_.values = function(obj) { var keys = _.keys(obj); var length = keys.length; var values = Array(length); //等同于new Array(length) for (var i = 0; i < length; i++) { values[i] = obj[keys[i]]; } return values; };
一開始看這種寫法,并不習慣,我們大多數人可能更習慣這樣寫(使用 push ):
_.values = function(obj) { var keys = _.keys(obj); var length = keys.length; var values = []; // for (var i = 0; i < length; i++) { values.push(obj[keys[i]]); //使用push } return values; };
實際測試中,第一種寫法會比第二種更快。
關鍵在于,我們事先知道要填充的數組 values 的長度,然后預先生成一個對應長度的數組,之后只需要給對應的位置賦值。而第二種在 push 的時候,除了給對應位置賦值,還需要改變 values 數組的 length。
所以,建議在已知長度的情況下,使用第一種,而不知道長度的情況下,使用第二種。
適當的使用 return function當我們編寫兩個功能非常相近的函數時,例如,實現復制一個數組的功能,分別是正序和倒序,我們可能會這樣子實現(這里只是為了舉例子,復制數組推薦第二點提到的使用slice或concat):
function copyArray(array, dir) { var copyArray = []; var i = dir > 0 ? 0 : array.length - 1; for (; i >= 0 && i < array.length; i += dir) { copyArray.push(array[i]); } return copyArray; } var copyDesc = function(array) { return copyArray(array, 1); }; var copyAsce = function(array) { return copyArray(array, -1); };
這樣子實現會有什么問題呢?
其實對copyDesc,copyAsce,來說,只有 dir 是不同的而已,但是,這種方式實現,卻需要將 array 也作為參數傳遞給 `copyArray。
而copyDesc,copyAsce其實只是一個轉發的作用而已。
我們可以繼續優化:
function copyArray(dir) { return function(array) { var copyArray = []; var i = dir > 0 ? 0 : array.length - 1; for (; i >= 0 && i < array.length; i += dir) { copyArray.push(array[i]); } return copyArray; }; } var copyDesc = copyArray(1); var copyAsce = copyArray(-1);
我覺得 return function 這種寫法比較優雅一點,你覺得呢?
類型判斷,使用 Object.prototype.toString()來判斷這里只舉兩個例子,isString,isArray,其他的例如 isArguments , isFunction , 由于有些瀏覽器兼容問題需要特殊處理,這里就不細說了。
而像isNull,isUndefined,這些比較簡單的,這里也不細說了:)
我們知道:
typeof 可能的返回值有:
類型 | 結果 |
---|---|
Undefined | "undefined" |
Null | "object" |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Symbol(ES6 新增) | "symbol" |
宿主對象(由 JS 環境提供) | Implementation-dependent |
函數對象( [[Call]]) | "function" |
任何其他對象 | "object" |
但是, typeof 卻有下面這種問題
typeof "test" ---> "string" typeof new String("test") ---> "object" typeof 123 -----> "number" typeof new Number(123) --->"object"
跟我們的期望不太一樣,Object.prototype.toString 則沒有這問題。
Object.prototype.toString.call("test"); //"[object String]" Object.prototype.toString.call(new String("test")); //"[object String]" Object.prototype.toString.call(123); //"[object Number]" Object.prototype.toString.call(new Number(123)); //"[object Number]"
所以,我們可以通過Object.prototype.toString來進行類型判斷
function isNumber(obj) { return Object.prototype.toString.call(obj) === "[object Number]"; } function isString(obj) { return Object.prototype.toString.call(obj) === "[object String]"; }待續。。。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100260.html
摘要:模塊化是隨著前端技術的發展,前端代碼爆炸式增長后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調也不等同于異步。將會討論安全的類型檢測惰性載入函數凍結對象定時器等話題。 Vue.js 前后端同構方案之準備篇——代碼優化 目前 Vue.js 的火爆不亞于當初的 React,本人對寫代碼有潔癖,代碼也是藝術。此篇是準備篇,工欲善其事,必先利其器。我們先在代...
摘要:來源于拉丁語,不要與混淆了。本文首先介紹一個簡單的使用優化技術的例子,然后解讀和庫中使用的源碼,加深理解。總結是一種優化技術,避免一些不必要的重復計算,可以提高計算速度。 memoization 來源于拉丁語 memorandum (to be remembered),不要與 memorization 混淆了。 首先來看一下維基百科的描述: In computing, memoizat...
摘要:專題系列共計篇,主要研究日常開發中一些功能點的實現,比如防抖節流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數組合專題系列第十六篇,講解函數組合,并且使用柯里化和函數組合實現模式需求我們需要寫一個函數,輸入,返回。 JavaScript 專題之從零實現 jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現一個 jQuery 的 ext...
摘要:本文同步自我得博客最近準備折騰一下,在事先了解了之后,我知道了對這個庫有著強依賴,正好之前也沒使用過,于是我就想先把徹底了解一下,這樣之后折騰的時候也少一點阻礙。 本文同步自我得博客:http://www.joeray61.com 最近準備折騰一下backbone.js,在事先了解了backbone之后,我知道了backbone對underscore這個庫有著強依賴,正好undersc...
摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。將轉為數組同時去掉第一個元素之后便可以調用方法總結數組的擴展方法就解讀到這里了,相關源碼可以參考這部分。放個預告,下一篇會暫緩下,講下相關的東西,敬請期待。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼,就好...
閱讀 1871·2021-11-25 09:43
閱讀 3161·2021-11-15 11:38
閱讀 2708·2019-08-30 13:04
閱讀 483·2019-08-29 11:07
閱讀 1492·2019-08-26 18:37
閱讀 2697·2019-08-26 14:07
閱讀 583·2019-08-26 13:52
閱讀 2278·2019-08-26 12:09