js函數(shù)操作

在js中萧求,函數(shù)本身屬于對(duì)象的一種,因此可以定義顶瞒、賦值夸政,作為對(duì)象的屬性或者成為其他函數(shù)的參數(shù)。函數(shù)名只是函數(shù)這個(gè)對(duì)象類的引用榴徐。

函數(shù)定義

3種函數(shù)定義的方式
1.函數(shù)聲明語(yǔ)句
使用function關(guān)鍵字守问,后跟一組參數(shù)以及函數(shù)體

function funcname(args1,args2){
 statement;
}

2.函數(shù)表達(dá)式
以表達(dá)式方式定義的函數(shù),函數(shù)的名稱是可選的

var  funcname=function(args1,args2){
statement;
}
var funcname=function funcname(args1,args2){
statement;
}

匿名函數(shù)也叫拉姆達(dá)函數(shù)坑资,是function關(guān)鍵字后面沒(méi)有標(biāo)識(shí)符的函數(shù)耗帕。
通常而言,以表達(dá)式定義函數(shù)時(shí)都不需要名稱袱贮,這會(huì)讓定義它們的代碼更加緊湊仿便。函數(shù)表達(dá)式特別適合用來(lái)定義那些只會(huì)使用一次的函數(shù)

var ten=(function(x){return x*x}(10));//定義同時(shí)進(jìn)行調(diào)用

一個(gè)函數(shù)定義表達(dá)式包含名稱,函數(shù)的局部作用域?qū)?huì)包含一個(gè)綁定到函數(shù)對(duì)象的名稱攒巍。實(shí)際上嗽仪,函數(shù)的名稱將成為函數(shù)內(nèi)部的一個(gè)局部變量。

var test=function fn(){
  return fn;
}
console.log(test);//fn(){return fn;}
console.log(test());//fn(){return fn;}
console.log(test()());//fn(){return fn;}

對(duì)于有具體名字的函數(shù)表達(dá)式來(lái)說(shuō)柒莉,函數(shù)名稱相當(dāng)于函數(shù)對(duì)象的形參闻坚,自能在函數(shù)內(nèi)部使用;而變量名稱相當(dāng)于函數(shù)對(duì)象的實(shí)參兢孝,在函數(shù)內(nèi)部和函數(shù)外部都可以使用窿凤。

var test=function fn(){
  return fn===test;
}
console.log(test());//true
console.log(test===fn);//fn is not defined

函數(shù)定義了一個(gè)非標(biāo)準(zhǔn)的name屬性,通過(guò)這個(gè)屬性可以訪問(wèn)到給定函數(shù)指定的名字跨蟹,這個(gè)屬性的值永遠(yuǎn)等于跟在function關(guān)鍵字后面的標(biāo)識(shí)符雳殊,匿名函數(shù)的name屬性為空。

//ie-11瀏覽器無(wú)效喷市,輸出undefined
//chrome在處理匿名函數(shù)時(shí)有問(wèn)題相种,會(huì)顯示函數(shù)表達(dá)式的名字
function fn(){}
console.log(fn.name);//fn
var fn=function(){};//''在chrome瀏覽器會(huì)顯示fn
var fn=function abc(){}
console.log(fn.name);//abc

3.function構(gòu)造函數(shù)
Function構(gòu)造函數(shù)接收任意數(shù)量的參數(shù),但是最后一個(gè)參數(shù)始終都被看成是函數(shù)體品姓,而前面的參數(shù)則枚舉出了新函數(shù)的參數(shù)

var funcname=new Function(args1,args2,'statement')

注意:Function構(gòu)造函數(shù)無(wú)法指定函數(shù)名稱寝并,它創(chuàng)建的是一個(gè)匿名函數(shù)。
從技術(shù)上講腹备,這是一個(gè)函數(shù)表達(dá)式衬潦。但是不推薦使用這種方式聲明函數(shù),這種語(yǔ)法會(huì)導(dǎo)致解析兩次代碼植酥。第一次是解析常規(guī)js代碼镀岛,第二次解析傳入構(gòu)造函數(shù)中的字符串弦牡,影響性能。

var sum=new Function('num1','num2','return num1+num2')
//等價(jià)于
var sum=function(num1,num2){
  return num1+num2;
}

Function()構(gòu)造函數(shù)創(chuàng)建的函數(shù)漂羊,其函數(shù)體的編譯總是會(huì)在全局作用域中執(zhí)行驾锰。于是,F(xiàn)unction()構(gòu)造函數(shù)類似于在全局作用域中執(zhí)行的eval()

var test=0;
functoin fn(){
  var test=1;
  return new Function('return test')
}
console.log(fn()());//0

并不是所有的函數(shù)都可以成為構(gòu)造函數(shù)

var a=new Math.min();//報(bào)錯(cuò)

函數(shù)聲明順序

函數(shù)聲明走越,相對(duì)于變量會(huì)優(yōu)先加載椭豫。所以不用擔(dān)心函數(shù)聲明在調(diào)用前還是調(diào)用后。
調(diào)用函數(shù)時(shí)會(huì)在本機(jī)活動(dòng)對(duì)象中查詢旨指,即當(dāng)前js文件中查詢赏酥,如果沒(méi)有才會(huì)向上查詢
,所以要是在兩個(gè)js文件中定義相同的函數(shù)名谆构,這兩個(gè)js文件內(nèi)部調(diào)用各自的函數(shù)裸扶,其他js文件調(diào)用最后聲明的函數(shù)。

重復(fù)

變量的重復(fù)聲明是無(wú)用的搬素,不會(huì)覆蓋同一作用域聲明的變量呵晨,但是函數(shù)的重復(fù)聲明會(huì)覆蓋前面的同名函數(shù)或同名變量。

//變量的重復(fù)聲明無(wú)用
var a=1;
var a;
console.log(a);//1
//覆蓋同名變量
var a;
function a(){
  console.log(1)
}
a();//1
//覆蓋同名函數(shù)
a();//2
function a(){
  console.log(a)
}
function a(){
  console.log(2)
}

刪除

函數(shù)聲明語(yǔ)句創(chuàng)建的變量無(wú)法刪除蔗蹋,這一點(diǎn)和變量聲明一樣何荚。

function foo(){
  console.log(1)
}
delete foo;
console.log(foo());//1

函數(shù)返回值

所有函數(shù)都有返回值,沒(méi)有return語(yǔ)句時(shí)猪杭,默認(rèn)返回內(nèi)容是undefined餐塘,和其他面向?qū)ο蟮木幊陶Z(yǔ)言一樣,return語(yǔ)句不會(huì)阻止finally子句的執(zhí)行皂吮。

function test(){
  try{
      return 2;
}catch(error){
  return 1;
}finally{
  return 0;
}
}
test();//0

如果函數(shù)調(diào)用時(shí)在前面加上了new前綴戒傻,且返回值不是一個(gè)對(duì)象,則返回this(該新對(duì)象)

function fn(){
    this.a=2;
    return 1;
}
var test=new fn();
console.log(test);//{a:2}
console.log(test.constructor);//fn(){this.a=2;return 1;}

如果返回值是一個(gè)對(duì)象蜂筹,則返回該對(duì)象需纳。

function fn(){
  this.a=2;
  return {a:1}
}
var test=new fn();
console.log(test);//{a:1}
console.log(test.constructor);//Object

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

js一共有四種調(diào)用模式:函數(shù)調(diào)用模式,方法調(diào)用模式艺挪,構(gòu)造器調(diào)用模式和間接調(diào)用模式不翩。
1.函數(shù)調(diào)用模式
當(dāng)一個(gè)函數(shù)并非一個(gè)對(duì)象的屬性時(shí),那么他就是被當(dāng)作一個(gè)函數(shù)來(lái)調(diào)用的麻裳。對(duì)于普通的函數(shù)調(diào)用來(lái)說(shuō)口蝠,函數(shù)的返回值就是調(diào)用表達(dá)式的值。

function add(x,y){
 return x+y;
}
var sum=add(3,4)
console.log(sum);//7

使用函數(shù)調(diào)用模式調(diào)用函數(shù)時(shí)津坑。非嚴(yán)格模式下妙蔗,this被綁定到全局對(duì)象;在嚴(yán)格模式下疆瑰,this是undefined

function add(x,y){
  console.log(this);//window
}
function add(x,y){
  'use strict';
  console.log(this);//undefined
}

因此眉反,this可以用來(lái)判斷當(dāng)前是否是嚴(yán)格模式昙啄。

var strict=(functioon(){return !this;}())

重寫(xiě):因?yàn)楹瘮?shù)調(diào)用模式的函數(shù)中的this綁定到全局對(duì)象,所以會(huì)發(fā)生全局屬性被重寫(xiě)的現(xiàn)象

var a=0;
function fn(){
  this.a=1;
}
fn();
console.log(this,this.a,a);//window 1 1

2.方法調(diào)用模式
當(dāng)一個(gè)函數(shù)被保存為對(duì)象的一個(gè)屬性時(shí)寸五,我們稱它為一個(gè)方法梳凛。當(dāng)一個(gè)方法被調(diào)用時(shí),this被綁定到該對(duì)象播歼。如果調(diào)用表達(dá)式包含一個(gè)提取屬性的動(dòng)作伶跷,那么它就是被當(dāng)作一個(gè)方法來(lái)調(diào)用掰读。

var o={
    m:function(){
      console.log(1)
  }
}
o.m();//1

方法可以使用this訪問(wèn)自己所屬的對(duì)象秘狞,所以它能從對(duì)象中取值或?qū)?duì)象進(jìn)行修改。this到對(duì)象的綁定發(fā)生在調(diào)用的時(shí)候蹈集。通過(guò)this可取的它們所屬對(duì)象的上下文的方法稱為公共方法烁试。

var o={
  a:1,
  m:function(){
      return this;
},
  n:function(){
    this.a=2;
}
}
console.log(o.m().a);//1
o.n();
console.log(o.m().a);//2

任何函數(shù)只要作為方法調(diào)用實(shí)際上都會(huì)傳入一個(gè)隱式的實(shí)參--這個(gè)參數(shù)是一個(gè)對(duì)象,方法調(diào)用的母體就是這個(gè)對(duì)象拢肆,通常來(lái)講减响,基于那個(gè)對(duì)象的方法可以執(zhí)行多次操作,方法調(diào)用的語(yǔ)法已經(jīng)清晰的表明了函數(shù)將基于一個(gè)對(duì)象進(jìn)行操作郭怪。

rect.setSize(width,height);
setRectSize(rect,width,height);

假設(shè)上面兩行代碼的功能完全一樣支示,它們都作用于一個(gè)假定的對(duì)象rect”刹牛可以看出颂鸿,第一行的方法調(diào)用語(yǔ)句非常清晰的表明這個(gè)函數(shù)執(zhí)行的載體是rect對(duì)象,函數(shù)中的所有操作將會(huì)基于這個(gè)對(duì)象攒庵。
和變量不同嘴纺,關(guān)鍵字this沒(méi)有作用域的限制,嵌套的函數(shù)不會(huì)調(diào)用它的函數(shù)中繼承this浓冒,如果嵌套函數(shù)作為方法調(diào)用栽渴,其this的值指向調(diào)用它的對(duì)象。如果嵌套函數(shù)作為函數(shù)調(diào)用稳懒,其this的值不是全局對(duì)象就是undefined

var o={
  m:function(){
    function n(){
        return this;
}
return n();
}
}
console.log(o.m());//window
var o={
  m:function(){
    function n(){
        'use strict'
return this;
}
return n()
}
}
console.log(o.m());//undefined

如果想訪問(wèn)這個(gè)外部函數(shù)的this值闲擦,需要將this的值保存在一個(gè)變量里,這個(gè)變量和內(nèi)部函數(shù)都同在一個(gè)作用域內(nèi)场梆。通常使用變量self或that來(lái)保存this.

var o={
 m:function(){
  var self=this;
  console.log(this===o);//true
  function n(){
    console.log(this===o);//false
    console.log(self===o);//true
    return self;  
}  
    return n()
}
}
console.log(o.m()===o);//true

3.構(gòu)造函數(shù)調(diào)用模式
如果函數(shù)或者方法調(diào)用之前帶有new關(guān)鍵字墅冷,它就構(gòu)成構(gòu)造函數(shù)調(diào)用。

function fn(){
  this.a=1;
}
var obj=new fn();
console.log(obj.a);//1

如果構(gòu)造函數(shù)調(diào)用在圓括號(hào)內(nèi)包含一組實(shí)參列表辙谜,先計(jì)算這些實(shí)參表達(dá)式俺榆,然后傳入函數(shù)內(nèi)

function fn(x){
    this.a=x;
}
var obj=new fn(2);
console.log(obj.a);//2

如果構(gòu)造函數(shù)沒(méi)有形參,js構(gòu)造函數(shù)調(diào)用的語(yǔ)法是允許省略實(shí)參列表和圓括號(hào)的装哆。凡是沒(méi)有形參的構(gòu)造函數(shù)都可以省略圓括號(hào)罐脊。

var o=new Object();
//等價(jià)于
var o=new Object;

注意:盡管構(gòu)造函數(shù)看起來(lái)像是一個(gè)方法調(diào)用定嗓,他依然會(huì)使用新對(duì)象作為調(diào)用上下文。也就是說(shuō):在表達(dá)式new o.m()中萍桌,調(diào)用上下文并不是o

var o={
  m:function(){
    return this;
}
}
var obj=new o.m();
console.log(obj,obj===o);//{},false
console.log(obj.constructor===o.m);//true

構(gòu)造函數(shù)通常不使用return關(guān)鍵字宵溅,他們通常初始化新對(duì)象,當(dāng)構(gòu)造函數(shù)的函數(shù)體執(zhí)行完畢時(shí)上炎,它會(huì)顯式返回恃逻。在這種情況下,構(gòu)造函數(shù)調(diào)用表達(dá)式的計(jì)算結(jié)果就是這個(gè)新對(duì)象的值藕施。

function fn(){
  this.a=2;
}
var test=new fn();
console.log(test);//{a:2}

如果構(gòu)造函數(shù)使用return語(yǔ)句但沒(méi)有指定返回值寇损,或者返回一個(gè)原始值,那么這時(shí)將忽略返回值裳食,同時(shí)使用這個(gè)新對(duì)象作為調(diào)用結(jié)果

function fn(){
    this.a = 2;
    return;
}
var test = new fn();
console.log(test);//{a:2}

如果構(gòu)造函數(shù)顯式地使用return語(yǔ)句返回一個(gè)對(duì)象矛市,那么調(diào)用表達(dá)式的值就是這個(gè)對(duì)象

var obj = {a:1};
function fn(){
    this.a = 2;
    return obj;
}
var test = new fn();
console.log(test);//{a:1}

4.間接調(diào)用模式
js中函數(shù)也是對(duì)象,函數(shù)對(duì)象也可以包含方法诲祸,call()和apply()方法可以用來(lái)間接的調(diào)用函數(shù)浊吏。
這兩個(gè)方法都允許顯式指定調(diào)用所需的this值,也就是所救氯,任何函數(shù)可以作為任何對(duì)象的方法來(lái)調(diào)用找田,哪怕這個(gè)函數(shù)不是對(duì)象的方法。兩個(gè)方法都可以指定調(diào)用的實(shí)參着憨。call()方法使用它自有的實(shí)參列表作為函數(shù)的實(shí)參墩衙。apply()方法則要求以數(shù)組的形式傳入?yún)?shù)。

var obj={};
function sun(x,y){
  return x+y;
}
console.log(sun.call(obj,1,2));//3
console.log(sun.apply(obj,[1,2]));//3

函數(shù)參數(shù)

arguments:js中的函數(shù)定義并未指明函數(shù)形參的類型享扔,函數(shù)調(diào)用也未對(duì)傳入的實(shí)參值做任何類型檢查底桂。實(shí)際上,js函數(shù)調(diào)用甚至不檢查傳入形參的個(gè)數(shù)惧眠。

function add(x){
  return x+1;
}
console.log(add(1));//2
console.log(add("1"));//11
console.log(add());//NaN
console.log(add(1,2));//2

同名形參:在非嚴(yán)格模式下籽懦,函數(shù)中可以出現(xiàn)同名形參,且只能訪問(wèn)最后出改名稱的形參氛魁。

function add(x,x,x){
  return x;
}
console.log(add(1,2,3));//3

而在嚴(yán)格模式下暮顺,出現(xiàn)同名形參拋出語(yǔ)法錯(cuò)誤。

function add(x,x,x){
  'use strict';
  return x;
}
console.log(add(1,2,3));//出現(xiàn)錯(cuò)誤

參數(shù)個(gè)數(shù):當(dāng)實(shí)參比函數(shù)聲明指定的形參個(gè)數(shù)少秀存,剩下的形參都將設(shè)置為undefined值捶码。

function add(x,y){
  console.log(x,y);
}
add(1);//1,undefined

常常使用邏輯或運(yùn)算符給省略的參數(shù)設(shè)置一個(gè)合理的默認(rèn)值。

function add(x,y){
  y=y||2;
  console.log(x,y)
}
add(1)

注意:實(shí)際上或链,使用y=y||2是不嚴(yán)謹(jǐn)?shù)谋鼓眨@示的設(shè)置值(undefined,null,false,0,-0,NaN)也會(huì)得到相同的結(jié)果。所以應(yīng)該根據(jù)實(shí)際場(chǎng)景進(jìn)行合理設(shè)置澳盐。
當(dāng)實(shí)參比形參個(gè)數(shù)要多時(shí)祈纯,剩下的實(shí)參沒(méi)有辦法直接獲得令宿,需要使用即將提到的arguments對(duì)象。
js中的參數(shù)在內(nèi)部用一個(gè)數(shù)組表示腕窥。函數(shù)接收到的始終都是這個(gè)數(shù)組粒没,而不關(guān)心數(shù)組中包含哪些參數(shù)。在函數(shù)體內(nèi)可以通過(guò)arguments對(duì)象來(lái)訪問(wèn)這個(gè)參數(shù)數(shù)組簇爆,從而獲得傳遞給參數(shù)的每一個(gè)參數(shù)癞松。arguments對(duì)象并不是array的實(shí)例,他是一個(gè)類數(shù)組對(duì)象入蛆,可以使用方括號(hào)訪問(wèn)它的每一個(gè)元素响蓉。

function add(x){
  console.log(arguments[0],arguments[1],arguments[2]);
 return x+1;
}
add(1,2,3)

arguments對(duì)象的length屬性顯示實(shí)參的個(gè)數(shù),函數(shù)的length屬性顯示形參的個(gè)數(shù)安寺。

function add(x,y){
  console.log(arguments.length) //3
  return x+1;
}
add(1,2,3);
console.log(add.length); //2

形參只是提供便利厕妖,但不是必需的

function add(){
     return arguments[0]+arguments[1];
}
console.log(add(1,2));//3

對(duì)象參數(shù):當(dāng)一個(gè)函數(shù)包含超過(guò)3個(gè)形參時(shí),要記住調(diào)用函數(shù)中實(shí)參的正確順序?qū)嵲谧屓祟^疼挑庶。

function arraycopy(/*array*/from,/*index*/form_start,/*array*/to,/*index*/to_start,/*integer*/length){
  //todo
}

通過(guò)鍵值對(duì)的形式來(lái)傳入?yún)?shù),這樣參數(shù)的順序就無(wú)關(guān)緊要了软能。定義函數(shù)的時(shí)候迎捺,傳入的實(shí)參都寫(xiě)入一個(gè)單獨(dú)的對(duì)象之中,在調(diào)用的時(shí)候傳入一個(gè)對(duì)象查排,對(duì)象中的名值對(duì)是真正需要的實(shí)參數(shù)據(jù)凳枝。

function easycopy(args){
  arraycopy(args.from,args.from_start||0,args.to,args.to_start||0,args.length);
}
var a=[1,2,3,4],b=[];
easycopy({from:a,to:b,length:4})

以參數(shù)為參數(shù)
函數(shù)本身是一個(gè)對(duì)象,因此可以將函數(shù)作為另一個(gè)函數(shù)的參數(shù)跋核,進(jìn)而實(shí)現(xiàn)函數(shù)回調(diào)岖瑰,功能等同于c++中的函數(shù)指針

function printf(str){
  dom1.innerText+=str.toString()+"\n";//設(shè)置dom1顯示的文字。變量也可以自動(dòng)調(diào)用其他js文件中的dom1變量砂代。dom1會(huì)先在當(dāng)前文件中查詢蹋订,然后向之前引用的js文件查詢,再向之后引用的js文件查詢
}
function callfunction(myfunction,myargument){           //函數(shù)作為其他函數(shù)的參數(shù)
    return myfunction(myargument);                      //調(diào)用回調(diào)函數(shù)
}

callfunction(printf,"hello world");

同步:當(dāng)形參與實(shí)參的個(gè)數(shù)相同時(shí)刻伊,arguments對(duì)象的值和對(duì)應(yīng)形參的值保持同步露戒。

function test(num1,num2){
  console.log(num1,arguments[0]);//1,1
arguments[0]=2;
console.log(num1,arguments[0]);//2,2
num1=10;
console.log(num1,arguments[0]);//10,10
}
test(1)

注意:雖然命名參數(shù)和對(duì)應(yīng)arguments對(duì)象的值相同,但并不是相同的命名空間捶箱。他們的命名空間是獨(dú)立的智什,但值是同步的
在嚴(yán)格模式下,arguments對(duì)象的值和參數(shù)的值都是獨(dú)立的丁屎。

function test(num1,num2){
  'use strict';
console.log(num1,arguments[0]);1,1
arguments[0]=2;
console.log(num1,arguments[0]);1,2
num1=10;
console.log(num1,arguments[0]);10,2
}
test(1)

當(dāng)形參并沒(méi)有對(duì)應(yīng)的實(shí)參時(shí)荠锭,arguments對(duì)象的值和形參的值并不對(duì)應(yīng)。

function test(num1,num2){
  console.log(num1,arguments[0]);//undefined,undefined
num1=10;
arguments[0]=5;
console.log(num1,arguments[0]);//10,5
}
test()

內(nèi)部屬性:callee
arguments對(duì)象有一個(gè)名為callee的屬性晨川,該屬性是一個(gè)指針证九,指向擁有這個(gè)arguments對(duì)象的函數(shù)
下面是經(jīng)典的階乘函數(shù)

function factorial(num){
  if(num<=1){
    return 1;
  }else{
    return num*factorial(num-1)
   }
}
console.log(factorial(5));//120

但是键思,上面這個(gè)函數(shù)的執(zhí)行與函數(shù)名字緊緊耦合在了一起,可以使用arguments.callee可以消除函數(shù)解耦

function fact(num){
  if(num<=1){
    return 1;
}else{
  return num*arguments.callee(num-1);
}
}
console.log(fact(5));//120

但是在嚴(yán)格模式下甫贯,訪問(wèn)這個(gè)屬性會(huì)拋出typeerror錯(cuò)誤

function factorial(num){
    'use strict';
    if(num <=1){
        return 1;
    }else{
        return num* arguments.callee(num-1);
    }
}    
//TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
console.log(factorial(5));

這時(shí)吼鳞,可以使用具名的函數(shù)表達(dá)式

var fact=function fn(num){
  if(num<=1){
    return 1;
}else{
  return num*fn(num-1)
}
}
console.log(fact(5))

caller:實(shí)際上,有兩個(gè)caller屬性
1:函數(shù)的caller
函數(shù)的caller屬性保存著調(diào)用當(dāng)前函數(shù)的函數(shù)的引用叫搁,如果實(shí)在全局作用域中調(diào)用當(dāng)前函數(shù)赔桌,它的值是null

function outer(){
  inner()
}
function inner(){
  console.log(inner.caller)//outer(){inner();}
}
outer()
function inner(){
  console.log(inner.caller);//null
}
inner()

在嚴(yán)格模式下,訪問(wèn)這個(gè)屬性會(huì)拋出typeerror錯(cuò)誤

function inner(){
  'use strict';
  console.log(inner.caller);
}
inner()

2:arguments對(duì)象的caller
該屬性始終是undefined渴逻,定義這個(gè)屬性是為了分清arguments.caller和函數(shù)的caller屬性

function inner(x){
    console.log(arguments.caller);//undefined
}
inner(1);

同樣地疾党,在嚴(yán)格模式下,訪問(wèn)這個(gè)屬性會(huì)拋出TypeError錯(cuò)誤

function inner(x){
    'use strict';
    //TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context
    console.log(arguments.caller);
}
inner(1);

函數(shù)重載

js函數(shù)不能像傳統(tǒng)意義上那樣實(shí)現(xiàn)重載惨奕。而在其他語(yǔ)言中雪位,可以為一個(gè)函數(shù)編寫(xiě)兩個(gè)定義,只要這兩個(gè)定義的簽名(接受的參數(shù)的類型和數(shù)量)不同即可梨撞。
js函數(shù)沒(méi)有簽名雹洗,因?yàn)槠鋮?shù)是由包含0個(gè)或者多個(gè)值得數(shù)組來(lái)表示的。而沒(méi)有函數(shù)簽名卧波,真正的重載是不可能做到的时肿。

//后面的聲明覆蓋了前面的聲明
function a(num){
  retun num+100;
}
functiona (num){
  return num+200;
}
var result=a(100);//300

只能通過(guò)檢查傳入函數(shù)中參數(shù)的類型和數(shù)量并做出不同的反應(yīng),來(lái)模仿方法的重載

function doAdd(){
  if(arguments.length==1){
    alert(arguments[0]+10)
}else if(arguments.length==2){
    alert(arguments[0]+arguments[2])
}
}
doAdd(10);//20
doAdd(30,20);//50

參數(shù)傳參

js中所有函數(shù)的參數(shù)都是按值傳遞的港粱,也就是說(shuō)螃成,把函數(shù)外部的值復(fù)制到函數(shù)內(nèi)部的參數(shù),就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣查坪。
1.基本類型值
在向參數(shù)傳遞基本類型的值時(shí)寸宏,被傳遞的值會(huì)被復(fù)制給一個(gè)局部變量(同名參數(shù)或arguments對(duì)象的一個(gè)元素)

function addTen(num){
  num+=10;
  return num;
}
var count=20;
var result=addTen(count);
console.log(count);//20
console.log(result);//30

2.引用類型值
在向參數(shù)傳遞引用類型的值時(shí),會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量偿曙,因此這個(gè)局部變量的變化會(huì)反應(yīng)在函數(shù)的外部氮凝。

function setName(obj){
    obj.name="test"
}
var person=new Object();
setName(person)
console.log(person.name);//test

當(dāng)在函數(shù)內(nèi)部重寫(xiě)引用類型的參數(shù)時(shí),這個(gè)變量的引用就是一個(gè)局部對(duì)象了遥昧。而這個(gè)局部對(duì)象會(huì)在函數(shù)執(zhí)行完畢后立即被銷毀覆醇。

function setName(obj){
  obj.name="test";
  console.log(person.name);//test
  obj=new Object();
  obj.name="white";
  console.log(person.name);//test
}
var person=new Object();
setName(person)

函數(shù)屬性

length屬性
arguments對(duì)象的length屬性表示實(shí)參個(gè)數(shù),而函數(shù)的length屬性則表示形參個(gè)數(shù)炭臭。

function add(x,y){
    console.log(arguments.length)//3
    console.log(add.length)//2
}
add(1,2,3)

name屬性
函數(shù)定義了一個(gè)非標(biāo)準(zhǔn)的name屬性永脓,通過(guò)這個(gè)屬性可以訪問(wèn)到給定函數(shù)指定的名字,這個(gè)屬性的值永遠(yuǎn)等于跟在function關(guān)鍵字后面的標(biāo)識(shí)符鞋仍,匿名函數(shù)的name屬性為空

//IE11-瀏覽器無(wú)效常摧,均輸出undefined
//chrome在處理匿名函數(shù)的name屬性時(shí)有問(wèn)題,會(huì)顯示函數(shù)表達(dá)式的名字
function fn(){};
console.log(fn.name);//'fn'
var fn = function(){};
console.log(fn.name);//'',在chrome瀏覽器中會(huì)顯示'fn'
var fn = function abc(){};
console.log(fn.name);//'abc'  

注意:name屬性早就被瀏覽器廣泛支持落午,但是直到es6才將其寫(xiě)入標(biāo)準(zhǔn)
es6對(duì)這個(gè)屬性的行為做出了一些修改谎懦,如果將一個(gè)匿名函數(shù)賦值給一個(gè)變量,es5的name屬性會(huì)返回空字符串溃斋,而es6的name屬性會(huì)返回實(shí)際的函數(shù)名

var fun=function(){}
fun.name;//es5 ""
fun.name;//es6 fun

如果將一個(gè)具名函數(shù)賦值給一個(gè)變量界拦,則es5和es6的name屬性都返回這個(gè)具名函數(shù)原本的名字

var bar=function baz(){}
bar.name;//es5 baz
bar.name;//es6 baz

Function構(gòu)造函數(shù)返回的函數(shù)實(shí)例,name屬性的值是“anonymous”

(new Function).name;//anonymous

bind返回的函數(shù)梗劫,name屬性值會(huì)加上“bound”前綴

function foo(){}
foo.bind({}).name;//bound foo
(function (){}).bind({}).name;//bound

prototype屬性
每一個(gè)函數(shù)都有一個(gè)prototype屬性享甸,這個(gè)屬性指向一個(gè)對(duì)象的引用,這個(gè)對(duì)象稱作原型對(duì)象梳侨。每一個(gè)函數(shù)都包含不同的原型對(duì)象蛉威。將函數(shù)用作構(gòu)造函數(shù)時(shí),新創(chuàng)建的對(duì)象會(huì)從原型對(duì)象上繼承屬性

function fn(){}
var obj=new fn;
fn.prototype.a=1;
console.log(obj.a);//1

函數(shù)方法

apply()和call()
每個(gè)函數(shù)都包含兩個(gè)非繼承而來(lái)的方法走哺,apply()和call().這兩個(gè)方法的用途都是在特定的作用域中調(diào)用函數(shù)蚯嫌,實(shí)際上等于函數(shù)體內(nèi)this對(duì)象的值。
要想以函數(shù)對(duì)象o的方法來(lái)調(diào)用函數(shù)f(),可以這樣使用call()和apply()

f.call(o)
f.apply(o)

假設(shè)o中不存在m方法丙躏,則等價(jià)于

o.m = f; //將f存儲(chǔ)為o的臨時(shí)方法
o.m(); //調(diào)用它择示,不傳入?yún)?shù)
delete o.m; //將臨時(shí)方法刪除

下面是一個(gè)實(shí)際的例子

window.color="red";
var o={color:"blue"};
function saycolor(){
  console.log(this.color)
}
sayColor()//red
sayColor.call(this);//red
sayColor.call(window);//red
sayColor.call(o);//blue
//sayColor.call(o)等價(jià)于
o.sayColor=sayColor;
o.sayColor();//blue
delete o.sayColor;

apply()方法接收兩個(gè)參數(shù):一個(gè)是在其中運(yùn)行函數(shù)的作用域(或者可以說(shuō)是要調(diào)用函數(shù)的母對(duì)象,它是調(diào)用上下文彼哼,在函數(shù)體內(nèi)通過(guò)this來(lái)獲得對(duì)他的引用)对妄,另一個(gè)是參數(shù)數(shù)組。其中敢朱,第二個(gè)參數(shù)可以是array的實(shí)例,也可以是arguments對(duì)象

function sum(num1,num2){
  return num1+num2;
}
//因?yàn)檫\(yùn)行函數(shù)的作用域是全局作用域摩瞎,所以this代表的是window對(duì)象
function callSum(num1,num2){
  return sum.apply(this,arguments)
}
function callSum2(num1,num2){
  return sum.apply(this,[num1,num2])
}
console.log(callSum(10,10));//20
console.log(callSum2(10,10));//20

call()方法與apply()方法的作用相同拴签,它們的區(qū)別僅僅在于接收參數(shù)的方式不同,對(duì)于call方法而言旗们,第一個(gè)參數(shù)是this值沒(méi)有變化蚓哩,變化的是其余參數(shù)都直接傳遞給函數(shù)。換句話說(shuō)上渴,在使用call()方法時(shí)岸梨,傳遞給函數(shù)的參數(shù)必須逐個(gè)列舉出來(lái)

function sum(num1, num2){
    return num1 + num2;
}
function callSum(num1, num2){
    return sum.call(this, num1, num2);
}
console.log(callSum(10,10));   //20

至于是使用apply()還是call(),完全取決于采取哪種函數(shù)傳遞參數(shù)的方式最方便。如果打算直接傳入arguments對(duì)象稠氮,或者包含函數(shù)中先接收到的也是一個(gè)數(shù)組曹阔,那么使用apply()肯定更方便,否則隔披,選擇call()可能更合適
在非嚴(yán)格模式下赃份,使用函數(shù)的call()或apply()方法時(shí),null或undefined值會(huì)被轉(zhuǎn)換為全局對(duì)象。而在嚴(yán)格模式下抓韩,函數(shù)的this值始終是指定的值

var color = 'red';
function displayColor(){
    console.log(this.color);
}
displayColor.call(null);//red
var color = 'red';
function displayColor(){
    'use strict';
    console.log(this.color);
}
displayColor.call(null);//TypeError: Cannot read property 'color' of null

應(yīng)用

1.調(diào)用對(duì)象的原生方法

var obj={};
obj.hasOwnProperty("toString");//false
obj.hasOwnProperty=function(){
  return true;
}
obj.hasOwnProperty("toString");//true
Object.prototype.hasOwnProperty.call(obj,"toString");false

2.找出數(shù)組中的最大值
js不提供找出數(shù)組最大元素的函數(shù)纠永,結(jié)合使用apply方法和math.max方法,就可以返回?cái)?shù)組的最大元素

var a=[1,33,2,4,5,6];
Math.max.apply(null,a)

3.將數(shù)組對(duì)象轉(zhuǎn)換成真正的數(shù)組

Array.prototype.slice.apply({0:1,length:1})//[1]
或者
[].prototype.slice.apply({0:1,length:1})

4.將一個(gè)數(shù)組的值push到另一個(gè)數(shù)組中

var a=[];
Array.prototype.push.apply(a,[1,2,3])
console.log(a);//[1,2,3]
Array.prototype.push.apply(a,[2,3,4]);
console.log(a);//[1,2,3,2,3,4]

5.綁定回調(diào)函數(shù)的對(duì)象
由于apply方法或者call方法不僅綁定函數(shù)執(zhí)行時(shí)所在的對(duì)象谒拴,還會(huì)立即執(zhí)行函數(shù)尝江,因此不得不把綁定語(yǔ)句寫(xiě)在函數(shù)體內(nèi),更簡(jiǎn)潔的寫(xiě)法是采用下面的bind方法

var o={};
o.f=function(){
    console.log(this===o)
}
var f=function(){
  o.f.apply(o)
}

bind()方法
bind()是es5新增的方法英上,這個(gè)方法的主要作用是將函數(shù)綁定到某個(gè)對(duì)象上
當(dāng)在函數(shù)f()上調(diào)用bind()方法并傳入一個(gè)對(duì)象o作為參數(shù)炭序,這個(gè)方法將返回一個(gè)新的對(duì)象。以函數(shù)調(diào)用的方式調(diào)用新的函數(shù)將會(huì)把原始的函數(shù)f()當(dāng)作o的方法調(diào)用善延,傳入新函數(shù)的任何實(shí)參都將傳入原始函數(shù)

function f(y){
  return this.x+y;
}
var o={x:1};
var g=f.bind(o);
g(2)

兼容代碼

function bind(f,o){
  if(f.bind){
  return f.bind(o)
}else{
  return function(){
  return f.apply(o,arguments)
}
}
}

bind方法不僅是將函數(shù)綁定到一個(gè)對(duì)象上少态,它還附帶一些其他應(yīng)用:除了第一個(gè)實(shí)參外,傳入bind的實(shí)參也會(huì)綁定到this易遣,這個(gè)附帶的應(yīng)用是一種常見(jiàn)的函數(shù)式編程及時(shí)彼妻,稱柯里化

var sum=function(x,y){
  return x+y;
}
var succ=sum.bind(null,1);
succ(2);//3,x綁定到1,并傳入2作為實(shí)參y
function f(y,z){
  return this.x+y+z;
}
var g=f.bind({x:1},2)
g(3);//6,this.x綁定到1豆茫,y綁定到2,z綁定到3

function getConfig(colors,size,other){
  console.log(colors,size,other)
}
var default=getConfig.bind(null,"#000","1024*234");
default("123")
default("456")

toString()
函數(shù)的toString()實(shí)例方法返回函數(shù)代碼的字符串侨歉,而靜態(tài)的toString()方法返回一個(gè)類似’[native code]’的字符串作為函數(shù)體

function test(){
  alert(1)
}
test.toString()
Function.toString()

toLocalString()
toLocalString()方法和toString()方法返回的結(jié)果相同

function test(){
    alert(1);//test
}
test.toLocaleString();/*"function test(){
                    alert(1);//test
                  }"*/
Function.toLocaleString();//"function Function() { [native code] }"
  

valueOf()
函數(shù)的valueOf()方法返回函數(shù)本身

function test(){
    alert(1);//test
}
test.valueOf();/*function test(){
                    alert(1);//test
                  }*/
typeof test.valueOf();//'function'
Function.valueOf();//Function() { [native code] }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市揩魂,隨后出現(xiàn)的幾起案子幽邓,更是在濱河造成了極大的恐慌,老刑警劉巖火脉,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牵舵,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡倦挂,警方通過(guò)查閱死者的電腦和手機(jī)畸颅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)方援,“玉大人没炒,你說(shuō)我怎么就攤上這事》赶罚” “怎么了送火?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)先匪。 經(jīng)常有香客問(wèn)我种吸,道長(zhǎng),這世上最難降的妖魔是什么胚鸯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任骨稿,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坦冠。我一直安慰自己形耗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布辙浑。 她就那樣靜靜地躺著激涤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪判呕。 梳的紋絲不亂的頭發(fā)上倦踢,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音侠草,去河邊找鬼辱挥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛边涕,可吹牛的內(nèi)容都是我干的晤碘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼功蜓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼园爷!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起式撼,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤童社,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后著隆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體扰楼,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年美浦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灭抑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抵代,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忘嫉,到底是詐尸還是另有隱情荤牍,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布庆冕,位于F島的核電站康吵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏访递。R本人自食惡果不足惜晦嵌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惭载,春花似錦旱函、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至含长,卻和暖如春券腔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拘泞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工纷纫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陪腌。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓辱魁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親偷厦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子商叹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容