• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

    javascript函數(shù)的五個(gè)運(yùn)用技巧介紹

    來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 19:28:59
    文檔

    javascript函數(shù)的五個(gè)運(yùn)用技巧介紹

    javascript函數(shù)的五個(gè)運(yùn)用技巧介紹:本篇文章給大家?guī)淼膬?nèi)容是關(guān)于javascript函數(shù)的五個(gè)運(yùn)用技巧介紹,有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)你有所幫助。函數(shù)對(duì)任何一門語言來說都是一個(gè)核心的概念,在javascript中更是如此。本文將介紹函數(shù)的5個(gè)高級(jí)技巧作用域安全的構(gòu)造函數(shù)
    推薦度:
    導(dǎo)讀javascript函數(shù)的五個(gè)運(yùn)用技巧介紹:本篇文章給大家?guī)淼膬?nèi)容是關(guān)于javascript函數(shù)的五個(gè)運(yùn)用技巧介紹,有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)你有所幫助。函數(shù)對(duì)任何一門語言來說都是一個(gè)核心的概念,在javascript中更是如此。本文將介紹函數(shù)的5個(gè)高級(jí)技巧作用域安全的構(gòu)造函數(shù)

    本篇文章給大家?guī)淼膬?nèi)容是關(guān)于javascript函數(shù)的五個(gè)運(yùn)用技巧介紹,有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)你有所幫助。

    函數(shù)對(duì)任何一門語言來說都是一個(gè)核心的概念,在javascript中更是如此。本文將介紹函數(shù)的5個(gè)高級(jí)技巧

    作用域安全的構(gòu)造函數(shù)

    構(gòu)造函數(shù)其實(shí)就是一個(gè)使用new操作符調(diào)用的函數(shù)

    function Person(name,age,job){
     this.name=name; 
     this.age=age; 
     this.job=job;
    }
    var person=new Person('match',28,'Software Engineer');
    console.log(person.name);//match

    如果沒有使用new操作符,原本針對(duì)Person對(duì)象的三個(gè)屬性被添加到window對(duì)象

    function Person(name,age,job){
     this.name=name; 
     this.age=age; 
     this.job=job;
    } 
    var person=Person('match',28,'Software Engineer');
    console.log(person);//undefinedconsole.log(window.name);//match

    window的name屬性是用來標(biāo)識(shí)鏈接目標(biāo)和框架的,這里對(duì)該屬性的偶然覆蓋可能會(huì)導(dǎo)致頁面上的其它錯(cuò)誤,這個(gè)問題的解決方法就是創(chuàng)建一個(gè)作用域安全的構(gòu)造函數(shù)

    function Person(name,age,job){
     if(this instanceof Person){
     this.name=name; 
     this.age=age; 
     this.job=job;
     }else{
     return new Person(name,age,job);
     }
    }var person=Person('match',28,'Software Engineer');
    console.log(window.name); // ""console.log(person.name); //'match'var person= new Person('match',28,'Software Engineer');
    console.log(window.name); // ""console.log(person.name); //'match'

    但是,對(duì)構(gòu)造函數(shù)竊取模式的繼承,會(huì)帶來副作用。這是因?yàn)椋铝写a中,this對(duì)象并非Polygon對(duì)象實(shí)例,所以構(gòu)造函數(shù)Polygon()會(huì)創(chuàng)建并返回一個(gè)新的實(shí)例

    function Polygon(sides){
     if(this instanceof Polygon){
     this.sides=sides; 
     this.getArea=function(){
     return 0;
     }
     }else{
     return new Polygon(sides);
     }
    }
    function Rectangle(wifth,height){
     Polygon.call(this,2); 
     this.width=this.width; 
     this.height=height; 
     this.getArea=function(){ 
     return this.width * this.height;
     };
    }
    var rect= new Rectangle(5,10);
    console.log(rect.sides); //undefined

    如果要使用作用域安全的構(gòu)造函數(shù)竊取模式的話,需要結(jié)合原型鏈繼承,重寫Rectangle的prototype屬性,使它的實(shí)例也變成Polygon的實(shí)例

    function Polygon(sides){
     if(this instanceof Polygon){
     this.sides=sides; 
     this.getArea=function(){
     return 0;
     }
     }else{
     return new Polygon(sides);
     }
    }
    function Rectangle(wifth,height){
     Polygon.call(this,2); 
     this.width=this.width; 
     this.height=height; 
     this.getArea=function(){
     return this.width * this.height;
     };
    }
    Rectangle.prototype= new Polygon();var rect= new Rectangle(5,10);
    console.log(rect.sides); //2

    惰性載入函數(shù)

    因?yàn)楦鳛g覽器之間的行為的差異,我們經(jīng)常會(huì)在函數(shù)中包含了大量的if語句,以檢查瀏覽器特性,解決不同瀏覽器的兼容問題。比如,我們最常見的為dom節(jié)點(diǎn)添加事件的函數(shù)

    function addEvent(type, element, fun) {
     if (element.addEventListener) {
     element.addEventListener(type, fun, false);
     } 
     else if(element.attachEvent){
     element.attachEvent('on' + type, fun);
     } else{
     element['on' + type] = fun;
     }
    }

    每次調(diào)用addEvent函數(shù)的時(shí)候,它都要對(duì)瀏覽器所支持的能力進(jìn)行檢查,首先檢查是否支持addEventListener方法,如果不支持,再檢查是否支持attachEvent方法,如果還不支持,就用dom0級(jí)的方法添加事件。這個(gè)過程,在addEvent函數(shù)每次調(diào)用的時(shí)候都要走一遍,其實(shí),如果瀏覽器支持其中的一種方法,那么他就會(huì)一直支持了,就沒有必要再進(jìn)行其他分支的檢測(cè)了。也就是說,if語句不必每次都執(zhí)行,代碼可以運(yùn)行的更快一些。

      解決方案就是惰性載入。所謂惰性載入,指函數(shù)執(zhí)行的分支只會(huì)發(fā)生一次,有兩種實(shí)現(xiàn)惰性載入的方式

      1、第一種是在函數(shù)被調(diào)用時(shí),再處理函數(shù)。函數(shù)在第一次調(diào)用時(shí),該函數(shù)會(huì)被覆蓋為另外一個(gè)按合適方式執(zhí)行的函數(shù),這樣任何對(duì)原函數(shù)的調(diào)用都不用再經(jīng)過執(zhí)行的分支了

      我們可以用下面的方式使用惰性載入重寫addEvent()

    function addEvent(type, element, fun) {
     if (element.addEventListener) {
     addEvent = function (type, element, fun) {
     element.addEventListener(type, fun, false);
     }
     } 
     else if(element.attachEvent){
     addEvent = function (type, element, fun) {
     element.attachEvent('on' + type, fun);
     }
     } 
     else{
     addEvent = function (type, element, fun) {
     element['on' + type] = fun;
     }
     } 
     return addEvent(type, element, fun);
    }

    在這個(gè)惰性載入的addEvent()中,if語句的每個(gè)分支都會(huì)為addEvent變量賦值,有效覆蓋了原函數(shù)。最后一步便是調(diào)用了新賦函數(shù)。下一次調(diào)用addEvent()時(shí),便會(huì)直接調(diào)用新賦值的函數(shù),這樣就不用再執(zhí)行if語句了

      但是,這種方法有個(gè)缺點(diǎn),如果函數(shù)名稱有所改變,修改起來比較麻煩

      2、第二種是聲明函數(shù)時(shí)就指定適當(dāng)?shù)暮瘮?shù)。 這樣在第一次調(diào)用函數(shù)時(shí)就不會(huì)損失性能了,只在代碼加載時(shí)會(huì)損失一點(diǎn)性能

      以下就是按照這一思路重寫的addEvent()。以下代碼創(chuàng)建了一個(gè)匿名的自執(zhí)行函數(shù),通過不同的分支以確定應(yīng)該使用哪個(gè)函數(shù)實(shí)現(xiàn)

    var addEvent = (function () {
     if (document.addEventListener) {
     return function (type, element, fun) {
     element.addEventListener(type, fun, false);
     }
     } 
     else if (document.attachEvent) {
     return function (type, element, fun) {
     element.attachEvent('on' + type, fun);
     }
     } 
     else { 
     return function (type, element, fun) {
     element['on' + type] = fun;
     }
     }
    })();

    函數(shù)綁定

    在javascript與DOM交互中經(jīng)常需要使用函數(shù)綁定,定義一個(gè)函數(shù)然后將其綁定到特定DOM元素或集合的某個(gè)事件觸發(fā)程序上,綁定函數(shù)經(jīng)常和回調(diào)函數(shù)及事件處理程序一起使用,以便把函數(shù)作為變量傳遞的同時(shí)保留代碼執(zhí)行環(huán)境

    <button id="btn">按鈕</button><script> 
     var handler={
     message:"Event handled.",
     handlerFun:function(){
     alert(this.message);
     }
     };
    btn.onclick = handler.handlerFun;
    </script>

    上面的代碼創(chuàng)建了一個(gè)叫做handler的對(duì)象。handler.handlerFun()方法被分配為一個(gè)DOM按鈕的事件處理程序。當(dāng)按下該按鈕時(shí),就調(diào)用該函數(shù),顯示一個(gè)警告框。雖然貌似警告框應(yīng)該顯示Event handled,然而實(shí)際上顯示的是undefiend。這個(gè)問題在于沒有保存handler.handleClick()的環(huán)境,所以this對(duì)象最后是指向了DOM按鈕而非handler

      可以使用閉包來修正這個(gè)問題

    <button id="btn">按鈕</button>
    <script> 
    var handler={
     message:"Event handled.",
     handlerFun:function(){
     alert(this.message);
     }
    };
    btn.onclick = function(){
     handler.handlerFun(); 
    }
    </script>

    當(dāng)然這是特定于此場(chǎng)景的解決方案,創(chuàng)建多個(gè)閉包可能會(huì)令代碼難以理解和調(diào)試。更好的辦法是使用函數(shù)綁定

      一個(gè)簡(jiǎn)單的綁定函數(shù)bind()接受一個(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);
     }
    }

    這個(gè)函數(shù)似乎簡(jiǎn)單,但其功能是非常強(qiáng)大的。在bind()中創(chuàng)建了一個(gè)閉包,閉包使用apply()調(diào)用傳入的函數(shù),并給apply()傳遞context對(duì)象和參數(shù)。當(dāng)調(diào)用返回的函數(shù)時(shí),它會(huì)在給定環(huán)境中執(zhí)行被傳入的函數(shù)并給出所有參數(shù)

    <button id="btn">按鈕</button><script> function bind(fn,context){ return function(){ return fn.apply(context,arguments);
     }
    } 
    var handler={
     message:"Event handled.",
     handlerFun:function(){
     alert(this.message);
     }
    };
    btn.onclick = bind(handler.handlerFun,handler);
    </script>

    ECMAScript5為所有函數(shù)定義了一個(gè)原生的bind()方法,進(jìn)一步簡(jiǎn)化了操作

      只要是將某個(gè)函數(shù)指針以值的形式進(jìn)行傳遞,同時(shí)該函數(shù)必須在特定環(huán)境中執(zhí)行,被綁定函數(shù)的效用就突顯出來了。它們主要用于事件處理程序以及setTimeout()和setInterval()。然而,被綁定函數(shù)與普通函數(shù)相比有更多的開銷,它們需要更多內(nèi)存,同時(shí)也因?yàn)槎嘀睾瘮?shù)調(diào)用稍微慢一點(diǎn),所以最好只在必要時(shí)使用

    函數(shù)柯里化

    與函數(shù)綁定緊密相關(guān)的主題是函數(shù)柯里化(function currying),它用于創(chuàng)建已經(jīng)設(shè)置好了一個(gè)或多個(gè)參數(shù)的函數(shù)。函數(shù)柯里化的基本方法和函數(shù)綁定是一樣的:使用一個(gè)閉包返回一個(gè)函數(shù)。兩者的區(qū)別在于,當(dāng)函數(shù)被調(diào)用時(shí),返回的函數(shù)還需要設(shè)置一些傳入的參數(shù)

    function add(num1,num2){
     return num1+num2;
    }function curriedAdd(num2){
     return add(5,num2);
    }
    console.log(add(2,3));//5console.log(curriedAdd(3));//8

    這段代碼定義了兩個(gè)函數(shù):add()和curriedAdd()。后者本質(zhì)上是在任何情況下第一個(gè)參數(shù)為5的add()版本。盡管從技術(shù)來說curriedAdd()并非柯里化的函數(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),
     finalArgs = args.concat(innerArgs); 
     return fn.apply(null, finalArgs);
     };
    }

    curry()函數(shù)的主要工作就是將被返回函數(shù)的參數(shù)進(jìn)行排序。curry()的第一個(gè)參數(shù)是要進(jìn)行柯里化的函數(shù),其他參數(shù)是要傳入的值。為了獲取第一個(gè)參數(shù)之后的所有參數(shù),在arguments對(duì)象上調(diào)用了slice()方法,并傳入?yún)?shù)1表示被返回的數(shù)組包含從第二個(gè)參數(shù)開始的所有參數(shù)。然后args數(shù)組包含了來自外部函數(shù)的參數(shù)。在內(nèi)部函數(shù)中,創(chuàng)建了innerArgs數(shù)組用來存放所有傳入的參數(shù)(又一次用到了slice())。有了存放來自外部函數(shù)和內(nèi)部函數(shù)的參數(shù)數(shù)組后,就可以使用concat()方法將它們組合為finalArgs,然后使用apply()將結(jié)果傳遞給函數(shù)。注意這個(gè)函數(shù)并沒有考慮到執(zhí)行環(huán)境,所以調(diào)用apply()時(shí)第一個(gè)參數(shù)是null。curry()函數(shù)可以按以下方式應(yīng)用

    function add(num1, num2){ 
    return num1 + num2;
    }var curriedAdd = curry(add, 5);
    alert(curriedAdd(3)); //8

    在這個(gè)例子中,創(chuàng)建了第一個(gè)參數(shù)綁定為5的add()的柯里化版本。當(dāng)調(diào)用cuurriedAdd()并傳入3時(shí),3會(huì)成為add()的第二個(gè)參數(shù),同時(shí)第一個(gè)參數(shù)依然是5,最后結(jié)果便是和8。也可以像下例這樣給出所有的函數(shù)參數(shù):

    function add(num1, num2){
     return num1 + num2;
    }
    var curriedAdd2 = curry(add, 5, 12);
    alert(curriedAdd2()); //17

    在這里,柯里化的add()函數(shù)兩個(gè)參數(shù)都提供了,所以以后就無需再傳遞給它們了

    函數(shù)柯里化還常常作為函數(shù)綁定的一部分包含在其中,構(gòu)造出更為復(fù)雜的bind()函數(shù)

    function bind(fn, context){
     var args = Array.prototype.slice.call(arguments, 2); 
     return function(){ 
     var innerArgs = Array.prototype.slice.call(arguments),
     finalArgs = args.concat(innerArgs); 
     return fn.apply(context, finalArgs);
     };
    }

    對(duì)curry()函數(shù)的主要更改在于傳入的參數(shù)個(gè)數(shù),以及它如何影響代碼的結(jié)果。curry()僅僅接受一個(gè)要包裹的函數(shù)作為參數(shù),而bind()同時(shí)接受函數(shù)和一個(gè)object對(duì)象。這表示給被綁定的函數(shù)的參數(shù)是從第三個(gè)開始而不是第二個(gè),這就要更改slice()的第一處調(diào)用。另一處更改是在倒數(shù)第3行將object對(duì)象傳給apply()。當(dāng)使用bind()時(shí),它會(huì)返回綁定到給定環(huán)境的函數(shù),并且可能它其中某些函數(shù)參數(shù)已經(jīng)被設(shè)好。要想除了event對(duì)象再額外給事件處理程序傳遞參數(shù)時(shí),這非常有用

    var handler = {
     message: "Event handled",
     handleClick: function(name, event){
     alert(this.message + ":" + name + ":" + event.type);
     }
    };
    var btn = document.getElementById("my-btn");
    EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler, "my-btn"));

    handler.handleClick()方法接受了兩個(gè)參數(shù):要處理的元素的名字和event對(duì)象。作為第三個(gè)參數(shù)傳遞給bind()函數(shù)的名字,又被傳遞給了handler.handleClick(),而handler.handleClick()也會(huì)同時(shí)接收到event對(duì)象

    ECMAScript5的bind()方法也實(shí)現(xiàn)函數(shù)柯里化,只要在this的值之后再傳入另一個(gè)參數(shù)即可

    var handler = {
     message: "Event handled",
     handleClick: function(name, event){
     alert(this.message + ":" + name + ":" + event.type);
     }
    };
    var btn = document.getElementById("my-btn");
    EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler, "my-btn"));

    javaScript中的柯里化函數(shù)和綁定函數(shù)提供了強(qiáng)大的動(dòng)態(tài)函數(shù)創(chuàng)建功能。使用bind()還是curry()要根據(jù)是否需要object對(duì)象響應(yīng)來決定。它們都能用于創(chuàng)建復(fù)雜的算法和功能,當(dāng)然兩者都不應(yīng)濫用,因?yàn)槊總€(gè)函數(shù)都會(huì)帶來額外的開銷

    函數(shù)重寫

    由于一個(gè)函數(shù)可以返回另一個(gè)函數(shù),因此可以用新的函數(shù)來覆蓋舊的函數(shù)

    function a(){
     console.log('a');
     a = function(){
     console.log('b');
     }
    }

    這樣一來,當(dāng)我們第一次調(diào)用該函數(shù)時(shí)會(huì)console.log('a')會(huì)被執(zhí)行;全局變量a被重定義,并被賦予新的函數(shù)

    當(dāng)該函數(shù)再次被調(diào)用時(shí), console.log('b')會(huì)被執(zhí)行

    再復(fù)雜一點(diǎn)的情況如下所示

    var a = (function(){
     function someSetup(){
     var setup = 'done';
     }
     function actualWork(){
     console.log('work');
     }
     someSetup(); 
     return actualWork;
    })()

    我們使用了私有函數(shù)someSetup()和actualWork(),當(dāng)函數(shù)a()第一次被調(diào)用時(shí),它會(huì)調(diào)用someSetup(),并返回函數(shù)actualWork()的引用.

    聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    javascript函數(shù)的五個(gè)運(yùn)用技巧介紹

    javascript函數(shù)的五個(gè)運(yùn)用技巧介紹:本篇文章給大家?guī)淼膬?nèi)容是關(guān)于javascript函數(shù)的五個(gè)運(yùn)用技巧介紹,有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)你有所幫助。函數(shù)對(duì)任何一門語言來說都是一個(gè)核心的概念,在javascript中更是如此。本文將介紹函數(shù)的5個(gè)高級(jí)技巧作用域安全的構(gòu)造函數(shù)
    推薦度:
    標(biāo)簽: 中的 方法 使用
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 久久精品亚洲中文字幕无码麻豆 | 亚洲AV第一页国产精品| 精品无人区麻豆乱码1区2区| 日韩午夜高清福利片在线观看欧美亚洲精品suv| 国产精品露脸国语对白| 中文字幕无码精品三级在线电影 | 国产伦精品免编号公布| 日韩一区二区三区精品| 国产精品 羞羞答答在线| 大伊香蕉精品一区视频在线 | 久久国产美女免费观看精品 | 婷婷精品国产亚洲AV麻豆不片| 久久精品国产精品亚洲下载| 久久精品国产一区二区三区日韩| 国产精品扒开腿做爽爽爽视频| 亚洲国产成人精品无码区在线观看| 国产线视频精品免费观看视频| 欧美亚洲国产精品久久蜜芽| 6一12呦女精品| 久久精品中文闷骚内射| 日本aⅴ精品中文字幕| 午夜成人精品福利网站在线观看| 国产香蕉国产精品偷在线| 99亚洲精品视频| www夜片内射视频日韩精品成人| 久久精品成人免费网站| 99在线精品视频| 55夜色66夜色国产精品视频| 国产精品久久久亚洲| 国产午夜无码精品免费看动漫 | 国产午夜精品一本在线观看 | 国产精品成人在线| 97久久综合精品久久久综合| 91精品国产高清91久久久久久| 亚洲AV日韩精品久久久久久久| 亚洲动漫精品无码av天堂| 亚洲av日韩精品久久久久久a| 久久亚洲精品成人av无码网站| 久久夜色精品国产噜噜麻豆| 精品无码国产一区二区三区51安| 久久精品毛片免费观看|