<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題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關鍵字專題關鍵字專題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
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        javascript函數的五個運用技巧介紹

        來源:懂視網 責編:小采 時間:2020-11-27 19:28:59
        文檔

        javascript函數的五個運用技巧介紹

        javascript函數的五個運用技巧介紹:本篇文章給大家帶來的內容是關于javascript函數的五個運用技巧介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。函數對任何一門語言來說都是一個核心的概念,在javascript中更是如此。本文將介紹函數的5個高級技巧作用域安全的構造函數
        推薦度:
        導讀javascript函數的五個運用技巧介紹:本篇文章給大家帶來的內容是關于javascript函數的五個運用技巧介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。函數對任何一門語言來說都是一個核心的概念,在javascript中更是如此。本文將介紹函數的5個高級技巧作用域安全的構造函數

        本篇文章給大家帶來的內容是關于javascript函數的五個運用技巧介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

        函數對任何一門語言來說都是一個核心的概念,在javascript中更是如此。本文將介紹函數的5個高級技巧

        作用域安全的構造函數

        構造函數其實就是一個使用new操作符調用的函數

        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操作符,原本針對Person對象的三個屬性被添加到window對象

        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屬性是用來標識鏈接目標和框架的,這里對該屬性的偶然覆蓋可能會導致頁面上的其它錯誤,這個問題的解決方法就是創建一個作用域安全的構造函數

        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'

        但是,對構造函數竊取模式的繼承,會帶來副作用。這是因為,下列代碼中,this對象并非Polygon對象實例,所以構造函數Polygon()會創建并返回一個新的實例

        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

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

        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

        惰性載入函數

        因為各瀏覽器之間的行為的差異,我們經常會在函數中包含了大量的if語句,以檢查瀏覽器特性,解決不同瀏覽器的兼容問題。比如,我們最常見的為dom節點添加事件的函數

        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;
         }
        }

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

          解決方案就是惰性載入。所謂惰性載入,指函數執行的分支只會發生一次,有兩種實現惰性載入的方式

          1、第一種是在函數被調用時,再處理函數。函數在第一次調用時,該函數會被覆蓋為另外一個按合適方式執行的函數,這樣任何對原函數的調用都不用再經過執行的分支了

          我們可以用下面的方式使用惰性載入重寫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);
        }

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

          但是,這種方法有個缺點,如果函數名稱有所改變,修改起來比較麻煩

          2、第二種是聲明函數時就指定適當的函數。 這樣在第一次調用函數時就不會損失性能了,只在代碼加載時會損失一點性能

          以下就是按照這一思路重寫的addEvent()。以下代碼創建了一個匿名的自執行函數,通過不同的分支以確定應該使用哪個函數實現

        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;
         }
         }
        })();

        函數綁定

        在javascript與DOM交互中經常需要使用函數綁定,定義一個函數然后將其綁定到特定DOM元素或集合的某個事件觸發程序上,綁定函數經常和回調函數及事件處理程序一起使用,以便把函數作為變量傳遞的同時保留代碼執行環境

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

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

          可以使用閉包來修正這個問題

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

        當然這是特定于此場景的解決方案,創建多個閉包可能會令代碼難以理解和調試。更好的辦法是使用函數綁定

          一個簡單的綁定函數bind()接受一個函數和一個環境,并返回一個在給定環境中調用給定函數的函數,并且將所有參數原封不動傳遞過去

        function bind(fn,context){
         return function(){ 
         return fn.apply(context,arguments);
         }
        }

        這個函數似乎簡單,但其功能是非常強大的。在bind()中創建了一個閉包,閉包使用apply()調用傳入的函數,并給apply()傳遞context對象和參數。當調用返回的函數時,它會在給定環境中執行被傳入的函數并給出所有參數

        <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為所有函數定義了一個原生的bind()方法,進一步簡化了操作

          只要是將某個函數指針以值的形式進行傳遞,同時該函數必須在特定環境中執行,被綁定函數的效用就突顯出來了。它們主要用于事件處理程序以及setTimeout()和setInterval()。然而,被綁定函數與普通函數相比有更多的開銷,它們需要更多內存,同時也因為多重函數調用稍微慢一點,所以最好只在必要時使用

        函數柯里化

        與函數綁定緊密相關的主題是函數柯里化(function currying),它用于創建已經設置好了一個或多個參數的函數。函數柯里化的基本方法和函數綁定是一樣的:使用一個閉包返回一個函數。兩者的區別在于,當函數被調用時,返回的函數還需要設置一些傳入的參數

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

        這段代碼定義了兩個函數:add()和curriedAdd()。后者本質上是在任何情況下第一個參數為5的add()版本。盡管從技術來說curriedAdd()并非柯里化的函數,但它很好地展示了其概念

          柯里化函數通常由以下步驟動態創建:調用另一個函數并為它傳入要柯里化的函數和必要參數。下面是創建柯里化函數的通用方式

        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()函數的主要工作就是將被返回函數的參數進行排序。curry()的第一個參數是要進行柯里化的函數,其他參數是要傳入的值。為了獲取第一個參數之后的所有參數,在arguments對象上調用了slice()方法,并傳入參數1表示被返回的數組包含從第二個參數開始的所有參數。然后args數組包含了來自外部函數的參數。在內部函數中,創建了innerArgs數組用來存放所有傳入的參數(又一次用到了slice())。有了存放來自外部函數和內部函數的參數數組后,就可以使用concat()方法將它們組合為finalArgs,然后使用apply()將結果傳遞給函數。注意這個函數并沒有考慮到執行環境,所以調用apply()時第一個參數是null。curry()函數可以按以下方式應用

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

        在這個例子中,創建了第一個參數綁定為5的add()的柯里化版本。當調用cuurriedAdd()并傳入3時,3會成為add()的第二個參數,同時第一個參數依然是5,最后結果便是和8。也可以像下例這樣給出所有的函數參數:

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

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

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

        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);
         };
        }

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

        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()方法接受了兩個參數:要處理的元素的名字和event對象。作為第三個參數傳遞給bind()函數的名字,又被傳遞給了handler.handleClick(),而handler.handleClick()也會同時接收到event對象

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

        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中的柯里化函數和綁定函數提供了強大的動態函數創建功能。使用bind()還是curry()要根據是否需要object對象響應來決定。它們都能用于創建復雜的算法和功能,當然兩者都不應濫用,因為每個函數都會帶來額外的開銷

        函數重寫

        由于一個函數可以返回另一個函數,因此可以用新的函數來覆蓋舊的函數

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

        這樣一來,當我們第一次調用該函數時會console.log('a')會被執行;全局變量a被重定義,并被賦予新的函數

        當該函數再次被調用時, console.log('b')會被執行

        再復雜一點的情況如下所示

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

        我們使用了私有函數someSetup()和actualWork(),當函數a()第一次被調用時,它會調用someSetup(),并返回函數actualWork()的引用.

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        javascript函數的五個運用技巧介紹

        javascript函數的五個運用技巧介紹:本篇文章給大家帶來的內容是關于javascript函數的五個運用技巧介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。函數對任何一門語言來說都是一個核心的概念,在javascript中更是如此。本文將介紹函數的5個高級技巧作用域安全的構造函數
        推薦度:
        標簽: 中的 方法 使用
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲精品无码高潮喷水在线| 五月天婷亚洲天综合网精品偷| 久久亚洲精品成人| baoyu777永久免费视频| 久久亚洲2019中文字幕| 一级毛片免费播放视频| 日韩一卡2卡3卡4卡新区亚洲| eeuss影院免费92242部| 日韩亚洲一区二区三区| 在线a免费观看最新网站| 亚洲性一级理论片在线观看| 免费国产作爱视频网站| 亚洲欧美日韩国产成人| 免费国产成人高清在线观看麻豆 | 最好免费观看高清在线| 久久国产亚洲观看| 97视频热人人精品免费| 亚洲国产精品美女久久久久| 国产亚洲福利一区二区免费看| 一级成人毛片免费观看| 亚洲视频精品在线| 最近中文字幕免费mv视频8| 污网站在线免费观看| 亚洲AV无码专区国产乱码电影| 69堂人成无码免费视频果冻传媒| 亚洲日韩精品无码专区| 亚洲日本韩国在线| 18禁成人网站免费观看| 18禁亚洲深夜福利人口| 国产亚洲精品岁国产微拍精品| 久视频精品免费观看99| 国产亚洲美女精品久久| 亚洲成av人影院| 日本免费电影一区| 精品国产一区二区三区免费| 亚洲熟妇av午夜无码不卡| 久久精品夜色噜噜亚洲A∨| 成人免费毛片内射美女-百度| 一级午夜免费视频| 亚洲人成高清在线播放| 中文字幕专区在线亚洲|