第22章 高級技巧

22.1 高級函數

22.1.1 安全的類型檢測

對于之前,我們要去判斷一個變量的類型,對于基本類型的,可以使用typeof,對于引用類型的,我們可以使用 instanceof ,不過,這兩種方法在某些情況下,是不可靠的,會存在一些兼容性問題。

接下來,我們介紹一種更佳可靠的檢測方法:

我們知道,在任何值上調用 Object 原生的 toString() 方法,都會返回一個 [object NativeConstrectorName] 格式的字符串,每個類在內部都有一個 [[Class]] 屬性,這個屬性中就指定了上述字符串中的構造函數名。

比如,我們可以使用下面方法來檢測各種對象:

function isArray(value){
   return Object.prototype.toString.call(value) === "[object Array]";
}

function isFunction(value){
   return Object.prototype.toString.call(value) === "[object Function]";
}

function isRegExp(value){
   return Object.prototype.toString.call(value) === "[object RegExp]";
}

22.1.2 作用域安全的構造函數

構造函數其實就是一個使用 new 操作符調用的函數。當使用 new 調用時,構造函數內用到的this對象會指向新創建的對象實例。

我們來看一個使用構造函數的例子:

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
}

var person = new Person('jack', 29, 'teacher');

person.name ==> 'jack'
person.age ==> 29
person.job ==> 'teacher'

可是?。?!
這個模式會出現一個問題,在你有意或者無意漏掉 new 操作符時,會發生以下事情

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
}

var person = Person('jack', 29, 'teacher');

person.name ==> 報錯

window.name ==> 'jack'
window.age ==> 29
window.job ==> 'teacher'

這是什么原因呢???

因為漏掉了 new 操作符后,Person()被作為普通函數調用,大家知道,普通函數內部的this指向了window,所以name,age,job
這三個屬性會被掛載到window對象上,造成全局變量污染。

這一點,對于構造函數來說,是一個極大的問題,怎么樣避免這個問題,可以更安全的使用自己的構造函數呢????

那就是:創建一個作用域安全的構造函數!!??!

function Person(myName, age, job){

  if( this instanceof Person ){
    this.myName = myName;
    this.age = age;
    this.job = job;
  } else {
    return new Person(myName, age, job);
  }
}

var person = Person('jack', 29, 'teacher');

window.myName ==> undefined
person.myName ==> 'jack'

22.1.3 惰性載入函數

22.1.4 函數綁定

22.1.5 函數柯里化

22.2 防篡改對象

22.2.1 不可擴展對象

默認情況下,所有對象都是可擴展的。

比如:

var person = { name: 'jack' };
person.age = 20;

如何禁止給對象添加擴展呢??可以使用對象的 Object.preventExtensions()方法

var person = { name: 'jack' };

Object.preventExtensions(person);

person.age = 20;

console.log(person.age) ==》 undefined

還有,使用 Object.isExtensible() 可以檢測對象是否可擴展

22.2.2 密封的對象

可以使用 Object.seal() 方法使一個對象成為密封對象。成為密封對象后,此對象將不可擴展,而且其屬性不可刪除,但是可以修改

var person = { name: 'jack' };
Object.seal(person);


delete person.name;
alert(person.name);  ==> 'jack'

person.name = 'pony';
alert(person.name) ==> 'pony';

可以使用 Object.isSealed() 來檢測對象是否被密封了。

22.2.3 凍結的對象

最嚴格的防篡改級別是凍結對象。凍結的對象,既不可擴展,又是密封,又不能修改其屬性。

即 Object.freeze();

對于一個JS庫而言,凍結對象是很有用的。因為可以極大的防止庫中核心對象被修改。

22.3 高級定時器

定時器對隊列的工作方式是:當特定事件過去后,將代碼插入。注意,給隊列添加代碼并不意味著代碼會立即執行,只能表示它會盡快執行。
等待瀏覽器線程空閑會執行。

使用 setInterval() 會存在以下問題:
(1) 某些間隔會被跳過
(2) 多個定時器的代碼執行之間的間隔可能會比預期的小。

所以,推薦使用 setTimeout() 來代替 setInterval()

22.3.2 Yielding Processes

不同于桌面應用往往能夠隨意控制他們要的內存大小和處理器時間,JS被嚴格限制了,以防止惡意的web程序員把用戶電腦搞掛了。

22.3.3 函數節流(重要概念)

在瀏覽器中,某些計算和處理要比其他的昂貴很多,其高頻率的更改可能會讓瀏覽器崩潰。為了繞開這個問題,你可以使用定時器對該函數進行節流。

函數節流背后的基本思想是指,某些代碼不可以在沒有間斷的情況連續重復執行。

該模式的基本形式:

var processor = {
  timeoutId: null,

  //實際進行處理的方法
  performProcessing: function(){
    //實際執行的代碼
  },

  //初始處理調用的方法
  process: function(){
    clearTimeout( this.timeoutId );

    var that = this;
    this.timeoutId = setTimeout(function(){
      that.performProcessing();
    },100);
  }
}

//嘗試開始執行
processor.process();

當調用了 process(),第一步是清除存好的 timeoutId,來阻止之前的調用被執行。然后創建一個新的定時器調用 performProcessing()。

可以將以上函數用下面這個函數來簡化

function throttle(method, context){
   clearTimeout( method.tId );
   method.tId = setTimeout(function(){
       method.call(context)
   },100)
}

接下來,我們再來看一個例子:

window.onresize = function(){
  var div = document.getElementById('myDiv');
  div.style.height = div.offsetWidth + 'px';
}

不知道大家有沒有意識到,上面這段代碼可能會帶來兩個問題:

(1):首先,要計算 offsetWidth 屬性,如果該元素或頁面上其他元素有非常復雜的CSS樣式,那么這個過程將會很復雜。
(2):其次,設置某個元素的高度需要對頁面進行回流來令改動生效。如果頁面有很多元素同時應用了相當數量的css,那么又會有很多計算。

節流優化后的代碼:

function resizeDiv(){
  var div = document.getElementById('myDiv');
  div.style.height = div.offsetWidth + 'px';
}

window.onresize = function(){
    throttle(resizeDiv);
}

總結,只要代碼是周期性執行的,都應該使用截流,比如以下js事件:input、scroll、resize等。

如果大家有人用過 underscore.js,里面有關于函數節流(throttle)與函數去抖(debounce)兩個方法,大家可以比較學習下

我貼個別人的鏈接http://www.cnblogs.com/fsjohnhuang/p/4147810.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,721評論 18 399
  • 22.1
    虎嗅添香閱讀 117評論 0 0
  • 前言 人生苦多,快來 Kotlin ,快速學習Kotlin! 什么是Kotlin? Kotlin 是種靜態類型編程...
    任半生囂狂閱讀 26,243評論 9 118
  • 這個世界上最偉大的是光榮的勝利比光榮的勝利更偉大的是誠實的失?。赫\實的失敗證明我們曾經嘗試過不可能的事。
    郭綠獅閱讀 209評論 0 1
  • ? One ?我記得,我上高中那會兒。我一姐們兒跟我一同班同學在一起了,倆人就天天膩在一塊兒。那會兒我姐們要去另一...
    小小小兒郎閱讀 684評論 0 0