摘要:語法如下注意這里使用的并不是的,是內(nèi)部函數(shù)的。函數(shù)柯里化的基本方法是使用一個(gè)閉包返回一個(gè)函數(shù)。當(dāng)函數(shù)被調(diào)用時(shí),返回的函數(shù)還需要設(shè)置一些傳入的參數(shù)。
安全的類型檢測
typeof操作符
檢測數(shù)據(jù)類型的結(jié)果可能會(huì)不正確;
instanceof操作符
操作符在多個(gè)全局作用域下存在問題:
var value = []; var isArray = value instanceof Array; console.log(isArray);
上述代碼都在全局作用域,返回true;但如果value在其他frame中,則返回false。
JSON對(duì)象
該對(duì)象也難以確定是否為原生對(duì)象;
解決辦法:
因?yàn)樵谌魏沃瞪险{(diào)用Object原生的toString()方法,都返回一個(gè)[Object NativeConstructorName]格式的字符串。每個(gè)類在內(nèi)部都有一個(gè)[[Class]]屬性,這個(gè)屬性指定了上述字符串中構(gòu)造函數(shù)的函數(shù)名,如:
console.log(Object.prototype.toString()); //[object Object] //利用call(): var value = []; console.log(Object.prototype.toString.call(value)); //[object Array] //進(jìn)一步完善: function whichType (value) { console.log(Object.prototype.toString.call(value)); } whichType("Obj"); //[boject String] whichType(["hello"]); //[object Array] whichType(321); //[object Number] //檢測是否為函數(shù): function isFunction (value) { return Object.prototype.toString.call(value) == "[object Function]"; } console.log(isFunction(Object.prototype.toString)); //true //檢測原生JSON對(duì)象: console.log(window.JSON && Object.prototype.toString.call(JSON) == "[object JSON]");
不適用于IE中COM對(duì)象形式實(shí)現(xiàn)的函數(shù)
作用域安全的構(gòu)造函數(shù)當(dāng)使用new調(diào)用構(gòu)造函數(shù)時(shí),構(gòu)造函數(shù)內(nèi)用到的this對(duì)象會(huì)指向新創(chuàng)建的對(duì)象實(shí)例,如:
function Person (name) { this.name = name; } var person = new Person("oliver"); console.log(person.name);
問題是當(dāng)沒有使用new操作符,直接調(diào)用構(gòu)造函數(shù),this會(huì)映射到全局對(duì)象window上,導(dǎo)致錯(cuò)誤對(duì)象屬性的意外增加:
function Person (name) { this.name = name; } var person = Person("oliver"); console.log(window.name); //oliver
解決辦法是創(chuàng)建一個(gè)作用域安全的構(gòu)造函數(shù):
function Person(name) { if (this instanceof Person) { //如果this是Person的實(shí)例 this.name = name; } else { return new Person(name); //否則調(diào)用new操作符 } } var person1 = Person("oliver"); console.log(person1.name); //oliver var person2 = new Person("troy"); console.log(person2.name); //troy console.log(window.name); //""
但是,如果使用構(gòu)造函數(shù)竊取模式的繼承且不實(shí)用原型鏈,那么這個(gè)繼承很可能被破壞如:
function Person(name) { if (this instanceof Person) { //如果this是Person的實(shí)例 this.name = name; } else { return new Person(name); //否則調(diào)用new操作符 } } function People (name,age) { Person.call(this, name); this.age = age; } var p = new People("Oliver", 18); console.log(p.name); //undefined console.log(p.age); //18
結(jié)合使用原型鏈或者寄生組合則可以解決這個(gè)問題:
function Person(name) { if (this instanceof Person) { //如果this是Person的實(shí)例 this.name = name; } else { return new Person(name); //否則調(diào)用new操作符 } } function People (name,age) { Person.call(this, name); this.age = age; } People.prototype = new Person(); //關(guān)鍵點(diǎn) var p = new People("Oliver", 18); console.log(p.name); //Oliver console.log(p.age); //18惰性載入函數(shù)
惰性函數(shù)就是函數(shù)執(zhí)行的分支僅會(huì)發(fā)生一次。
第一種就是在函數(shù)被調(diào)用時(shí)再處理函數(shù):
function createXHR () { if (typeof XMLHttpRequest !== "undefined") { createXHR = function () { //關(guān)鍵點(diǎn) return new XMLHttpRequest(); } } else if (typeof ActiveXObject !== "undefined") { createXHR = function () { //關(guān)鍵點(diǎn) return new ActiveXObject(["MSXML2.XMLHttp"]); } } else { createXHR = function () { //關(guān)鍵點(diǎn) throw new Error("No XHR object available."); } } return createXHR(); //關(guān)鍵點(diǎn) }第二種
就是指定適當(dāng)?shù)暮瘮?shù):
function createXHR () { if (typeof XMLHttpRequest !== "undefined") { return function () { //關(guān)鍵點(diǎn) return new XMLHttpRequest(); } } else if (typeof ActiveXObject !== "undefined") { return function () { //關(guān)鍵點(diǎn) return new ActiveXObject(["MSXML2.XMLHttp"]); } } else { return function () { //關(guān)鍵點(diǎn) throw new Error("No XHR object available."); } } return createXHR(); //關(guān)鍵點(diǎn) }函數(shù)綁定
函數(shù)綁定要?jiǎng)?chuàng)建一個(gè)函數(shù), 可以在特定的this環(huán)境中以指定參數(shù)調(diào)用另一個(gè)函數(shù)。 該技巧常常和回調(diào)函數(shù)與事件處理程序一起使用, 以便在將函數(shù)作為變量傳遞的同時(shí)保留代碼的執(zhí)行環(huán)境。 由于代碼之中存在著this變量, 而this在當(dāng)前環(huán)境下指向確定的對(duì)象, 但是當(dāng)更改代碼的執(zhí)行環(huán)境時(shí), 就會(huì)出現(xiàn)問題了。 為了解決這個(gè)問題, javascript函數(shù)庫中實(shí)現(xiàn)了一個(gè)bind() 函數(shù)來解決這個(gè)問題。
一個(gè)簡單的bind() 函數(shù)接收一個(gè)函數(shù)和一個(gè)環(huán)境, 并返回一個(gè)在給定環(huán)境中調(diào)用給定函數(shù)的函數(shù), 并且將所有參數(shù)原封不動(dòng)傳遞過去。 語法如下:
function bind(fn, context) { return function() { return fn.apply(context, arguments); } }
注意這里使用的arguments并不是bind() 的, 是內(nèi)部函數(shù)的。
var handler = { message: "Event handled", handleClick: function(event) { alert(this.message); } }; var btn = document.getElementById("my-btn"); EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler));
ECMAScript5為所有函數(shù)定義了一個(gè)原生的bind() 方法, 進(jìn)一步簡化了操作。
var handler = { message: "Event handled", handleClick: function(event) { alert(this.message); } }; var btn = document.getElementById("my-btn"); EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler));
它們主要用于事件處理程序以及setTimeout() 和setInterval()。 然而被綁定函數(shù)與普通函數(shù)相比有更多的開銷, 它們需要更多內(nèi)存, 同時(shí)也因?yàn)槎嘀睾瘮?shù)調(diào)用稍微慢一些, 所以最好只在必要時(shí)使用。
函數(shù)柯里化它用于創(chuàng)建已經(jīng)設(shè)置好了一個(gè)或多個(gè)參數(shù)的函數(shù)。 函數(shù)柯里化的基本方法是: 使用一個(gè)閉包返回一個(gè)函數(shù)。 當(dāng)函數(shù)被調(diào)用時(shí), 返回的函數(shù)還需要設(shè)置一些傳入的參數(shù)。
柯里化函數(shù)通常由以下步驟動(dòng)態(tài)的創(chuàng)建: 調(diào)用另一個(gè)函數(shù)并為它傳入要柯里化的函數(shù)和必要參數(shù)。 下面是創(chuàng)建柯里化函數(shù)的通用方式:
function curry(fn) { var args = Array.prototype.slice.call(arguments, 1); return function() { var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); return fn.apply(null, finalArgs); } }
這種變化也需要額外的開銷
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78791.html
摘要:為了規(guī)避這個(gè)問題,可以使用定時(shí)器對(duì)事件處理程序進(jìn)行節(jié)流。當(dāng)?shù)诙握{(diào)用該函數(shù)時(shí),它會(huì)清除前一次的定時(shí)器,并設(shè)置另一個(gè)。如果前一個(gè)定時(shí)器已經(jīng)執(zhí)行過了,這個(gè)操作就沒有任何意義。然而如果前一個(gè)定時(shí)器尚未執(zhí)行,其實(shí)就是將其替換為一個(gè)新的定時(shí)器。 高級(jí)定時(shí)器 為了解決setInterval的一些執(zhí)行問題, 下面是采用鏈?zhǔn)絪etTimeout的方式來規(guī)避: setTimeout(function()...
摘要:防篡改對(duì)象不可擴(kuò)展對(duì)象默認(rèn)情況下,所有對(duì)象都是可擴(kuò)展的不可擴(kuò)展可以使用這個(gè)方法嚴(yán)格模式下會(huì)拋出錯(cuò)誤一旦設(shè)置防擴(kuò)展,對(duì)象就無法添加新的屬性和方法。已有的屬性方法不受影響,這些屬性方法仍然可以修改和刪除。檢測是否被凍結(jié),用方法 防篡改對(duì)象 不可擴(kuò)展對(duì)象 默認(rèn)情況下,所有對(duì)象都是可擴(kuò)展的: var person = { name: Oliver }; person.age = 18;...
摘要:關(guān)于定時(shí)器要記住的最重要的事情是指定的時(shí)間間隔表示何時(shí)將定時(shí)器的代碼添加到隊(duì)列,而不是何時(shí)實(shí)際執(zhí)行代碼。多個(gè)定時(shí)器之間的執(zhí)行間隔會(huì)比預(yù)期的小解決辦法處理中數(shù)組分塊,,函數(shù)節(jié)流,實(shí)際進(jìn)行處理的方法實(shí)際執(zhí)行的代碼初始處理調(diào)用的方法 一、高級(jí)函數(shù) 安全類型檢測 Object.protitype.toString.call(value) 作用域安全的構(gòu)造函數(shù) function Pers...
摘要:如果你對(duì)函數(shù)式編程有一定了解,函數(shù)柯里化是不可或缺的,利用函數(shù)柯里化,可以在開發(fā)中非常優(yōu)雅的處理復(fù)雜邏輯。同樣先看簡單版本的方法,以方法為例,代碼來自高級(jí)程序設(shè)計(jì)加強(qiáng)版實(shí)現(xiàn)上面函數(shù),可以換成任何其他函數(shù),經(jīng)過函數(shù)處理,都可以轉(zhuǎn)成柯里化函數(shù)。 我們經(jīng)常說在Javascript語言中,函數(shù)是一等公民,它們本質(zhì)上是十分簡單和過程化的??梢岳煤瘮?shù),進(jìn)行一些簡單的數(shù)據(jù)處理,return 結(jié)果,...
摘要:封裝方法也比較簡單,書中對(duì)此問題也進(jìn)行了處理使用定時(shí)器,讓函數(shù)延遲秒后執(zhí)行,在此秒內(nèi),然后函數(shù)再次被調(diào)用,則刪除上次的定時(shí)器,取消上次調(diào)用的隊(duì)列任務(wù),重新設(shè)置定時(shí)器。 在實(shí)際開發(fā)中,函數(shù)一定是最實(shí)用最頻繁的一部分,無論是以函數(shù)為核心的函數(shù)式編程,還是更多人選擇的面向?qū)ο笫降木幊蹋紩?huì)有函數(shù)的身影,所以對(duì)函數(shù)進(jìn)行深入的研究是非常有必要的。 函數(shù)節(jié)流 比較直白的說,函數(shù)節(jié)流就是強(qiáng)制規(guī)定一...
閱讀 2490·2021-11-24 09:39
閱讀 3532·2019-08-30 15:53
閱讀 607·2019-08-29 15:15
閱讀 2913·2019-08-26 13:23
閱讀 3228·2019-08-26 10:48
閱讀 654·2019-08-26 10:31
閱讀 780·2019-08-26 10:30
閱讀 2373·2019-08-23 18:32