欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何編寫高質(zhì)量JS代碼(續(xù))

 更新時(shí)間:2015年02月25日 10:09:58   投稿:hebedich  
本文是如何編寫高質(zhì)量JS代碼系列文章的第二篇,前篇文章反響還不錯(cuò),應(yīng)小伙伴們的要求,今天繼續(xù)此系列的文章,有需要的小伙伴參考下。

繼續(xù)上一篇文章《如何編寫高質(zhì)量JS代碼》今次整理一下javascript函數(shù)知識(shí)點(diǎn)。

2.使用函數(shù)

函數(shù)給程序員提供了主要的抽象功能,又提供實(shí)現(xiàn)機(jī)制。函數(shù)可以獨(dú)立實(shí)現(xiàn)其他語(yǔ)言中的多個(gè)不同的特性,例如,過(guò)程、方法、構(gòu)造函數(shù),甚至類或模塊。

2.1 理解函數(shù)調(diào)用、方法調(diào)用以及構(gòu)造函數(shù)調(diào)用之間的不同

針對(duì)面向?qū)ο缶幊?,函?shù)、方法和類的構(gòu)造函數(shù)是三種不同的概念。

使用模式:

1,函數(shù)調(diào)用

復(fù)制代碼 代碼如下:

function hello(username){
    return "hello" + username;
}

2,方法調(diào)用

復(fù)制代碼 代碼如下:

var obj = {
    hello : function(){
        return "hello , " + this.username;
    },
    username : "floraLam"
};
ohj.hello();//"hello ,  floraLam"

this變量被綁定到對(duì)象是由于hello方法被定義在obj對(duì)象中,我們也可以子啊另外一個(gè)對(duì)象中賦值一份相同的函數(shù)引用,并得到相同的答案。

復(fù)制代碼 代碼如下:

var obj2 = {
    hello : obj.hello(),
    username : "floraLam"
};

3,構(gòu)造函數(shù)使用

復(fù)制代碼 代碼如下:

function User(name,passwordHash){
    this.name = name;
    this.passwordHash = passwordHash;
}

使用new操作符來(lái)調(diào)用User則視為構(gòu)造函數(shù)。

復(fù)制代碼 代碼如下:

var u  = new User("floraLam","123");

 與函數(shù)調(diào)用和方法調(diào)用不同的是,構(gòu)造函數(shù)調(diào)用將一個(gè)全新的對(duì)象作為this變量的值,并隱式返回這個(gè)新對(duì)象作為調(diào)用結(jié)果。構(gòu)造函數(shù)的主要職責(zé)是初始化該新對(duì)象。

2.2 熟練掌握高階函數(shù)

高階函數(shù)無(wú)非是那些將函數(shù)作為參數(shù)或返回值的函數(shù),將函數(shù)作為參數(shù)(通常稱為回調(diào)函數(shù),因?yàn)楦唠A函數(shù)"隨后調(diào)用"它)是一種特別強(qiáng)大、富有表現(xiàn)力的慣用法,也在js程序中被大量使用。

考慮數(shù)組的標(biāo)準(zhǔn)sort方法,為了對(duì)所有數(shù)組都能工作,sort方法需要調(diào)用者決定如何比較數(shù)組中的任意兩個(gè)元素。

復(fù)制代碼 代碼如下:

function compareNumber(x,y){
    if(x < y){
        return -1;
    }
    if(x > y){
        return 1;
    }
    return 0;
}
[3,1,4,1,5,9].sort(compareNumbers);//[1,1,3,4,5,9]

復(fù)制代碼 代碼如下:

[3,1,4,1,5,9].sort(function(x,y){
    if(x < y){
        return -1;
    }
    if(x > y){
        return 1;
    }
    return 0;
});//[1,1,3,4,5,9]

上述例子使用一個(gè)匿名函數(shù)進(jìn)一步簡(jiǎn)化。

學(xué)會(huì)使用高階函數(shù)通常可以簡(jiǎn)化代碼并消除繁瑣的樣板代碼。簡(jiǎn)單的轉(zhuǎn)換字符串?dāng)?shù)組的操作我們可以使用循環(huán)這樣實(shí)現(xiàn):

復(fù)制代碼 代碼如下:

var names = ["Fred","Wilma","Pebbles"];
var upper = [];
for(var i = 0,n = names.length ;i< n;i++){
    upper[i] = names[i].toUpperCase();
}
upper;//["FRED","WILMA","PEBBLES"];

使用數(shù)組便利的map方法,可以消除循環(huán),僅僅使用一個(gè)局部函數(shù)就可以對(duì)元素的逐個(gè)轉(zhuǎn)換。

復(fù)制代碼 代碼如下:

var names = ["Fred","Wilma","Pebbles"];
var upper = names.map(function(name){
    return name.toUpperCase();
});
upper;//["FRED","WILMA","PEBBLES"];

另外,例如我們想創(chuàng)建若干個(gè)方法創(chuàng)建不同的字符串,具有共同的實(shí)現(xiàn)邏輯,每個(gè)循環(huán)通過(guò)連接每個(gè)獨(dú)立部分的計(jì)算結(jié)果來(lái)創(chuàng)建一個(gè)字符串。

復(fù)制代碼 代碼如下:

 function bulidString(n,callback){
     var result = "";
     for(var i = 0 ; i < n ;i++){
         result += callback(i);
     }
     return  result;
 }
 var alphabet = bulidString(26,function(i){
     return String.fromCharCode(aIndex + i);
 });
 alphabet;//"abcdefghijklmnopqrxtuvwxyz";
 var digits = buildString(10,function(i){ return i;})
 digits;//"0123456789"
 var random = buildString(9,function(){
     random += String.fromCharCode(Math.floor(Math.random()*26)+aIndex
 });
 random;//"yefjmcef"(隨機(jī))

這樣能夠使得讀者更清晰了解該代碼能做什么,無(wú)須深入實(shí)現(xiàn)細(xì)節(jié)。

備注

   javascript返回指定范圍的隨機(jī)數(shù)(m-n之間)的公式:Math.random()*(n-m)+m

  同時(shí)要注意題目要求,是否要求返回正整數(shù)

2.3調(diào)用模式

調(diào)用一個(gè)函數(shù)將會(huì)暫停當(dāng)前函數(shù)的執(zhí)行,傳遞控制權(quán)與參數(shù)給新的函數(shù)。 除了聲明時(shí)定義的形式參數(shù),每個(gè)函數(shù)會(huì)接收到兩個(gè)新的附加參數(shù):this和arguments。

this是個(gè)很重要的參數(shù),并且它的值是由調(diào)用模式?jīng)Q定的。

以下是JavaScript中很重要的4個(gè)調(diào)用模式:

a. 方法調(diào)用模式the method invocation pattern
b. 函數(shù)調(diào)用模式the function invocation pattern
c. 構(gòu)造器調(diào)用模式the constructor invocation pattern
d. Apply調(diào)用模式the apply invocation pattern

這些模式在如何初始化關(guān)鍵參數(shù)this上存在差異

1. 方法調(diào)用模式the method invocation method

當(dāng)函數(shù)作為對(duì)象的方法的時(shí)候,我們就叫函數(shù)為方法。當(dāng)一個(gè)方法被調(diào)用的時(shí)候,this綁定到調(diào)用的對(duì)象。

復(fù)制代碼 代碼如下:

var myObj={
    val:0,
    increment:function(inc){
         this.val+=typeof inc ==="number"?    inc:1;
    },
    get_val:function(){return this.val;}
}
myObj.increment();// 1
myObj["increment"](2);//3   

小結(jié):

1、通過(guò)this可取得它們所屬對(duì)象的上下文的方法稱為公共方法

2、當(dāng)用 .或者下標(biāo)表達(dá)式 來(lái)使用一個(gè)函數(shù)的時(shí)候,就是方法調(diào)用模式,this對(duì)象綁定到前面的對(duì)象。

3,一個(gè)函數(shù)可以使用this來(lái)訪問(wèn)對(duì)象,所以它能檢索對(duì)象的值或者更改對(duì)象的值。綁定this到對(duì)象發(fā)生在調(diào)用的時(shí)候。

2. 函數(shù)調(diào)用模式the function invocation pattern

當(dāng)一個(gè)函數(shù)不是一個(gè)對(duì)象的屬性,那么它就是作為函數(shù)來(lái)調(diào)用的。當(dāng)一個(gè)函數(shù)作為函數(shù)調(diào)用模式來(lái)調(diào)用的時(shí)候,this綁定到全局對(duì)象。這是JavaScript設(shè)計(jì)時(shí)的錯(cuò)誤并延續(xù)了下來(lái)。

復(fù)制代碼 代碼如下:

function add(x,y){
  return x+y;
}
myObj.double=function(){
    var that=this;
    var helper=function(){
        that.val=add(that.value,that.value);
        //錯(cuò)誤的寫法可能是這樣,為什么錯(cuò)呢?因?yàn)楹瘮?shù)作為內(nèi)部函數(shù)調(diào)用的時(shí)候,this已經(jīng)綁定到了錯(cuò)誤的對(duì)象,全局對(duì)象并沒(méi)有val屬性,所以返回不正確的值。
        //this.val = this.val+this.val;
  }
  helper();
}
myObj.double();//6       

3. 構(gòu)造器調(diào)用模式the constructor invocation pattern

JavaScript是一門基于原型繼承的語(yǔ)言,這意味著對(duì)象可以直接繼承屬性從其它的對(duì)象,該語(yǔ)言是無(wú)類別的。

如果在一個(gè)函數(shù)前面帶上new來(lái)調(diào)用,那么將得到一個(gè)隱藏連接到該函數(shù)的prototype成員的新對(duì)象,同時(shí)this也將會(huì)綁定到該新對(duì)象。

new前綴也會(huì)改變r(jià)eturn語(yǔ)句的行為。這也不是推薦的編程方式。

復(fù)制代碼 代碼如下:

var Foo = function(status){
    this.status = status;
}
Foo.prototype.get_status = function(){
    return this.status;
}
//構(gòu)造一個(gè)Foo實(shí)例
var myFoo = new Foo("bar");
myFoo.get_status();//"bar"

4. Apply調(diào)用模式the apply invocation pattern

因?yàn)镴avaScript是一個(gè)函數(shù)式的面向?qū)ο笳Z(yǔ)言,所以函數(shù)可以擁有方法。

Apply方法擁有兩個(gè)參數(shù),第一個(gè)是將綁定到this的值,第二個(gè)是參數(shù)數(shù)組,也就是說(shuō)Apply方法讓我們構(gòu)建一個(gè)數(shù)組并用其去調(diào)用函數(shù),即允許我們選擇this的值,也允許我們選擇數(shù)組的值。

復(fù)制代碼 代碼如下:

var array = [3,4];
var sum = add.apply(null,array); // 7
var statusObj = {status:"ABCDEFG"};
Foo.prototype.pro_get_status = function(prefix){
    return prefix +"-"+this.status;
}
var status = Foo.prototype.get_status.apply(statusObj);// "ABCDEFG"
var pro_status = Foo.prototype.get_status.apply(statusObj,["prefix"]);// "prefix -ABCDEFG"

通常情況下,函數(shù)或方法的接收者(級(jí)綁定到特殊關(guān)鍵字this的值)是由調(diào)用者的語(yǔ)法決定性的。特別地,方法調(diào)用語(yǔ)法將方法被查找對(duì)象綁定到this變量。然而,有時(shí)需要使用自定義接收者來(lái)調(diào)用函數(shù)。這時(shí)候就需要使用call方法或者bind方法自定義接收者來(lái)調(diào)用方法

 2.4 使用bind方法提取具有確定接受者的方法

由于方法與值為函數(shù)的屬性沒(méi)有區(qū)別,因此也容易提取對(duì)象的方法并提取出函數(shù)作為回調(diào)函數(shù)直接傳遞給高階函數(shù)。

但這也很容易忘記將提取出來(lái)的函數(shù)的接受著綁定到該函數(shù)被提取出的對(duì)象上。

復(fù)制代碼 代碼如下:

var buffer = {
     entries: [],
     add :function(s){
         this.entries.push(s);
     }   
}
var source = ["867","-","5309"];
source.forEach(butter.add);//error:entries is undefined

這個(gè)時(shí)候butter.add的接受者不是butter對(duì)象。函數(shù)的接收者取決于它是如何被調(diào)用的,forEach方法在全局作用域中被調(diào)用,因此forEach方法的實(shí)現(xiàn)使用全局對(duì)象作為默認(rèn)的接收者,由于全局對(duì)象中沒(méi)有entries屬性,因此這段代碼拋出錯(cuò)誤。

forEach方法允許調(diào)用者提供一個(gè)可選的參數(shù)作為回調(diào)函數(shù)的接收者。

復(fù)制代碼 代碼如下:

var source = ["867","-","5309"];
source.forEach(butter.add,butter);

但并非所有高階函數(shù)都細(xì)心周到為使用者提供回調(diào)函數(shù)的接收者。

解決方法有兩種:

1)創(chuàng)建一個(gè)顯式地一buffer對(duì)象方法的方式調(diào)用add的封裝函數(shù)。不管封裝函數(shù)如何被調(diào)用,它總能確保將其參數(shù)推送到目標(biāo)數(shù)組中。

復(fù)制代碼 代碼如下:

var source = ["867","-","5309"];
source.forEach(function(s){
    butter.add(s);
});

2)函數(shù)對(duì)象的bind方法需要一個(gè)接收者對(duì)象,并產(chǎn)生一個(gè)以該接收者對(duì)象的方法調(diào)用的方法調(diào)用原來(lái)的函數(shù)的封裝函數(shù)。

復(fù)制代碼 代碼如下:

var source = ["867","-","5309"];
source.forEach(butter.add.bind(buffer));

備注

  buffer.add.bind(buffer)創(chuàng)建一個(gè)新函數(shù)而不是修改buffer.add函數(shù):

  buffer.add === buffer.add.bind(buffer); //false

以上就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。

相關(guān)文章

最新評(píng)論