在js中,函數本身屬于對象的一種,因此可以定義、賦值,作為對象的屬性或者成為其他函數的參數。函數名只是函數這個對象類的引用。
函數定義
3種函數定義的方式
1.函數聲明語句
使用function關鍵字,后跟一組參數以及函數體
function funcname(args1,args2){
statement;
}
2.函數表達式
以表達式方式定義的函數,函數的名稱是可選的
var funcname=function(args1,args2){
statement;
}
var funcname=function funcname(args1,args2){
statement;
}
匿名函數也叫拉姆達函數,是function關鍵字后面沒有標識符的函數。
通常而言,以表達式定義函數時都不需要名稱,這會讓定義它們的代碼更加緊湊。函數表達式特別適合用來定義那些只會使用一次的函數
var ten=(function(x){return x*x}(10));//定義同時進行調用
一個函數定義表達式包含名稱,函數的局部作用域將會包含一個綁定到函數對象的名稱。實際上,函數的名稱將成為函數內部的一個局部變量。
var test=function fn(){
return fn;
}
console.log(test);//fn(){return fn;}
console.log(test());//fn(){return fn;}
console.log(test()());//fn(){return fn;}
對于有具體名字的函數表達式來說,函數名稱相當于函數對象的形參,自能在函數內部使用;而變量名稱相當于函數對象的實參,在函數內部和函數外部都可以使用。
var test=function fn(){
return fn===test;
}
console.log(test());//true
console.log(test===fn);//fn is not defined
函數定義了一個非標準的name屬性,通過這個屬性可以訪問到給定函數指定的名字,這個屬性的值永遠等于跟在function關鍵字后面的標識符,匿名函數的name屬性為空。
//ie-11瀏覽器無效,輸出undefined
//chrome在處理匿名函數時有問題,會顯示函數表達式的名字
function fn(){}
console.log(fn.name);//fn
var fn=function(){};//''在chrome瀏覽器會顯示fn
var fn=function abc(){}
console.log(fn.name);//abc
3.function構造函數
Function構造函數接收任意數量的參數,但是最后一個參數始終都被看成是函數體,而前面的參數則枚舉出了新函數的參數
var funcname=new Function(args1,args2,'statement')
注意:Function構造函數無法指定函數名稱,它創建的是一個匿名函數。
從技術上講,這是一個函數表達式。但是不推薦使用這種方式聲明函數,這種語法會導致解析兩次代碼。第一次是解析常規js代碼,第二次解析傳入構造函數中的字符串,影響性能。
var sum=new Function('num1','num2','return num1+num2')
//等價于
var sum=function(num1,num2){
return num1+num2;
}
Function()構造函數創建的函數,其函數體的編譯總是會在全局作用域中執行。于是,Function()構造函數類似于在全局作用域中執行的eval()
var test=0;
functoin fn(){
var test=1;
return new Function('return test')
}
console.log(fn()());//0
并不是所有的函數都可以成為構造函數
var a=new Math.min();//報錯
函數聲明順序
函數聲明,相對于變量會優先加載。所以不用擔心函數聲明在調用前還是調用后。
調用函數時會在本機活動對象中查詢,即當前js文件中查詢,如果沒有才會向上查詢
,所以要是在兩個js文件中定義相同的函數名,這兩個js文件內部調用各自的函數,其他js文件調用最后聲明的函數。
重復
變量的重復聲明是無用的,不會覆蓋同一作用域聲明的變量,但是函數的重復聲明會覆蓋前面的同名函數或同名變量。
//變量的重復聲明無用
var a=1;
var a;
console.log(a);//1
//覆蓋同名變量
var a;
function a(){
console.log(1)
}
a();//1
//覆蓋同名函數
a();//2
function a(){
console.log(a)
}
function a(){
console.log(2)
}
刪除
函數聲明語句創建的變量無法刪除,這一點和變量聲明一樣。
function foo(){
console.log(1)
}
delete foo;
console.log(foo());//1
函數返回值
所有函數都有返回值,沒有return語句時,默認返回內容是undefined,和其他面向對象的編程語言一樣,return語句不會阻止finally子句的執行。
function test(){
try{
return 2;
}catch(error){
return 1;
}finally{
return 0;
}
}
test();//0
如果函數調用時在前面加上了new前綴,且返回值不是一個對象,則返回this(該新對象)
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;}
如果返回值是一個對象,則返回該對象。
function fn(){
this.a=2;
return {a:1}
}
var test=new fn();
console.log(test);//{a:1}
console.log(test.constructor);//Object
函數調用
js一共有四種調用模式:函數調用模式,方法調用模式,構造器調用模式和間接調用模式。
1.函數調用模式
當一個函數并非一個對象的屬性時,那么他就是被當作一個函數來調用的。對于普通的函數調用來說,函數的返回值就是調用表達式的值。
function add(x,y){
return x+y;
}
var sum=add(3,4)
console.log(sum);//7
使用函數調用模式調用函數時。非嚴格模式下,this被綁定到全局對象;在嚴格模式下,this是undefined
function add(x,y){
console.log(this);//window
}
function add(x,y){
'use strict';
console.log(this);//undefined
}
因此,this可以用來判斷當前是否是嚴格模式。
var strict=(functioon(){return !this;}())
重寫:因為函數調用模式的函數中的this綁定到全局對象,所以會發生全局屬性被重寫的現象
var a=0;
function fn(){
this.a=1;
}
fn();
console.log(this,this.a,a);//window 1 1
2.方法調用模式
當一個函數被保存為對象的一個屬性時,我們稱它為一個方法。當一個方法被調用時,this被綁定到該對象。如果調用表達式包含一個提取屬性的動作,那么它就是被當作一個方法來調用。
var o={
m:function(){
console.log(1)
}
}
o.m();//1
方法可以使用this訪問自己所屬的對象,所以它能從對象中取值或對對象進行修改。this到對象的綁定發生在調用的時候。通過this可取的它們所屬對象的上下文的方法稱為公共方法。
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
任何函數只要作為方法調用實際上都會傳入一個隱式的實參--這個參數是一個對象,方法調用的母體就是這個對象,通常來講,基于那個對象的方法可以執行多次操作,方法調用的語法已經清晰的表明了函數將基于一個對象進行操作。
rect.setSize(width,height);
setRectSize(rect,width,height);
假設上面兩行代碼的功能完全一樣,它們都作用于一個假定的對象rect。可以看出,第一行的方法調用語句非常清晰的表明這個函數執行的載體是rect對象,函數中的所有操作將會基于這個對象。
和變量不同,關鍵字this沒有作用域的限制,嵌套的函數不會調用它的函數中繼承this,如果嵌套函數作為方法調用,其this的值指向調用它的對象。如果嵌套函數作為函數調用,其this的值不是全局對象就是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
如果想訪問這個外部函數的this值,需要將this的值保存在一個變量里,這個變量和內部函數都同在一個作用域內。通常使用變量self或that來保存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.構造函數調用模式
如果函數或者方法調用之前帶有new關鍵字,它就構成構造函數調用。
function fn(){
this.a=1;
}
var obj=new fn();
console.log(obj.a);//1
如果構造函數調用在圓括號內包含一組實參列表,先計算這些實參表達式,然后傳入函數內
function fn(x){
this.a=x;
}
var obj=new fn(2);
console.log(obj.a);//2
如果構造函數沒有形參,js構造函數調用的語法是允許省略實參列表和圓括號的。凡是沒有形參的構造函數都可以省略圓括號。
var o=new Object();
//等價于
var o=new Object;
注意:盡管構造函數看起來像是一個方法調用,他依然會使用新對象作為調用上下文。也就是說:在表達式new o.m()中,調用上下文并不是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
構造函數通常不使用return關鍵字,他們通常初始化新對象,當構造函數的函數體執行完畢時,它會顯式返回。在這種情況下,構造函數調用表達式的計算結果就是這個新對象的值。
function fn(){
this.a=2;
}
var test=new fn();
console.log(test);//{a:2}
如果構造函數使用return語句但沒有指定返回值,或者返回一個原始值,那么這時將忽略返回值,同時使用這個新對象作為調用結果
function fn(){
this.a = 2;
return;
}
var test = new fn();
console.log(test);//{a:2}
如果構造函數顯式地使用return語句返回一個對象,那么調用表達式的值就是這個對象
var obj = {a:1};
function fn(){
this.a = 2;
return obj;
}
var test = new fn();
console.log(test);//{a:1}
4.間接調用模式
js中函數也是對象,函數對象也可以包含方法,call()和apply()方法可以用來間接的調用函數。
這兩個方法都允許顯式指定調用所需的this值,也就是所,任何函數可以作為任何對象的方法來調用,哪怕這個函數不是對象的方法。兩個方法都可以指定調用的實參。call()方法使用它自有的實參列表作為函數的實參。apply()方法則要求以數組的形式傳入參數。
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
函數參數
arguments:js中的函數定義并未指明函數形參的類型,函數調用也未對傳入的實參值做任何類型檢查。實際上,js函數調用甚至不檢查傳入形參的個數。
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
同名形參:在非嚴格模式下,函數中可以出現同名形參,且只能訪問最后出改名稱的形參。
function add(x,x,x){
return x;
}
console.log(add(1,2,3));//3
而在嚴格模式下,出現同名形參拋出語法錯誤。
function add(x,x,x){
'use strict';
return x;
}
console.log(add(1,2,3));//出現錯誤
參數個數:當實參比函數聲明指定的形參個數少,剩下的形參都將設置為undefined值。
function add(x,y){
console.log(x,y);
}
add(1);//1,undefined
常常使用邏輯或運算符給省略的參數設置一個合理的默認值。
function add(x,y){
y=y||2;
console.log(x,y)
}
add(1)
注意:實際上,使用y=y||2是不嚴謹的,顯示的設置值(undefined,null,false,0,-0,NaN)也會得到相同的結果。所以應該根據實際場景進行合理設置。
當實參比形參個數要多時,剩下的實參沒有辦法直接獲得,需要使用即將提到的arguments對象。
js中的參數在內部用一個數組表示。函數接收到的始終都是這個數組,而不關心數組中包含哪些參數。在函數體內可以通過arguments對象來訪問這個參數數組,從而獲得傳遞給參數的每一個參數。arguments對象并不是array的實例,他是一個類數組對象,可以使用方括號訪問它的每一個元素。
function add(x){
console.log(arguments[0],arguments[1],arguments[2]);
return x+1;
}
add(1,2,3)
arguments對象的length屬性顯示實參的個數,函數的length屬性顯示形參的個數。
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
對象參數:當一個函數包含超過3個形參時,要記住調用函數中實參的正確順序實在讓人頭疼。
function arraycopy(/*array*/from,/*index*/form_start,/*array*/to,/*index*/to_start,/*integer*/length){
//todo
}
通過鍵值對的形式來傳入參數,這樣參數的順序就無關緊要了。定義函數的時候,傳入的實參都寫入一個單獨的對象之中,在調用的時候傳入一個對象,對象中的名值對是真正需要的實參數據。
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})
以參數為參數
函數本身是一個對象,因此可以將函數作為另一個函數的參數,進而實現函數回調,功能等同于c++中的函數指針
function printf(str){
dom1.innerText+=str.toString()+"\n";//設置dom1顯示的文字。變量也可以自動調用其他js文件中的dom1變量。dom1會先在當前文件中查詢,然后向之前引用的js文件查詢,再向之后引用的js文件查詢
}
function callfunction(myfunction,myargument){ //函數作為其他函數的參數
return myfunction(myargument); //調用回調函數
}
callfunction(printf,"hello world");
同步:當形參與實參的個數相同時,arguments對象的值和對應形參的值保持同步。
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)
注意:雖然命名參數和對應arguments對象的值相同,但并不是相同的命名空間。他們的命名空間是獨立的,但值是同步的
在嚴格模式下,arguments對象的值和參數的值都是獨立的。
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)
當形參并沒有對應的實參時,arguments對象的值和形參的值并不對應。
function test(num1,num2){
console.log(num1,arguments[0]);//undefined,undefined
num1=10;
arguments[0]=5;
console.log(num1,arguments[0]);//10,5
}
test()
內部屬性:callee
arguments對象有一個名為callee的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數
下面是經典的階乘函數
function factorial(num){
if(num<=1){
return 1;
}else{
return num*factorial(num-1)
}
}
console.log(factorial(5));//120
但是,上面這個函數的執行與函數名字緊緊耦合在了一起,可以使用arguments.callee可以消除函數解耦
function fact(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
console.log(fact(5));//120
但是在嚴格模式下,訪問這個屬性會拋出typeerror錯誤
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));
這時,可以使用具名的函數表達式
var fact=function fn(num){
if(num<=1){
return 1;
}else{
return num*fn(num-1)
}
}
console.log(fact(5))
caller:實際上,有兩個caller屬性
1:函數的caller
函數的caller屬性保存著調用當前函數的函數的引用,如果實在全局作用域中調用當前函數,它的值是null
function outer(){
inner()
}
function inner(){
console.log(inner.caller)//outer(){inner();}
}
outer()
function inner(){
console.log(inner.caller);//null
}
inner()
在嚴格模式下,訪問這個屬性會拋出typeerror錯誤
function inner(){
'use strict';
console.log(inner.caller);
}
inner()
2:arguments對象的caller
該屬性始終是undefined,定義這個屬性是為了分清arguments.caller和函數的caller屬性
function inner(x){
console.log(arguments.caller);//undefined
}
inner(1);
同樣地,在嚴格模式下,訪問這個屬性會拋出TypeError錯誤
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);
函數重載
js函數不能像傳統意義上那樣實現重載。而在其他語言中,可以為一個函數編寫兩個定義,只要這兩個定義的簽名(接受的參數的類型和數量)不同即可。
js函數沒有簽名,因為其參數是由包含0個或者多個值得數組來表示的。而沒有函數簽名,真正的重載是不可能做到的。
//后面的聲明覆蓋了前面的聲明
function a(num){
retun num+100;
}
functiona (num){
return num+200;
}
var result=a(100);//300
只能通過檢查傳入函數中參數的類型和數量并做出不同的反應,來模仿方法的重載
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
參數傳參
js中所有函數的參數都是按值傳遞的,也就是說,把函數外部的值復制到函數內部的參數,就和把值從一個變量復制到另一個變量一樣。
1.基本類型值
在向參數傳遞基本類型的值時,被傳遞的值會被復制給一個局部變量(同名參數或arguments對象的一個元素)
function addTen(num){
num+=10;
return num;
}
var count=20;
var result=addTen(count);
console.log(count);//20
console.log(result);//30
2.引用類型值
在向參數傳遞引用類型的值時,會把這個值在內存中的地址復制給一個局部變量,因此這個局部變量的變化會反應在函數的外部。
function setName(obj){
obj.name="test"
}
var person=new Object();
setName(person)
console.log(person.name);//test
當在函數內部重寫引用類型的參數時,這個變量的引用就是一個局部對象了。而這個局部對象會在函數執行完畢后立即被銷毀。
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)
函數屬性
length屬性
arguments對象的length屬性表示實參個數,而函數的length屬性則表示形參個數。
function add(x,y){
console.log(arguments.length)//3
console.log(add.length)//2
}
add(1,2,3)
name屬性
函數定義了一個非標準的name屬性,通過這個屬性可以訪問到給定函數指定的名字,這個屬性的值永遠等于跟在function關鍵字后面的標識符,匿名函數的name屬性為空
//IE11-瀏覽器無效,均輸出undefined
//chrome在處理匿名函數的name屬性時有問題,會顯示函數表達式的名字
function fn(){};
console.log(fn.name);//'fn'
var fn = function(){};
console.log(fn.name);//'',在chrome瀏覽器中會顯示'fn'
var fn = function abc(){};
console.log(fn.name);//'abc'
注意:name屬性早就被瀏覽器廣泛支持,但是直到es6才將其寫入標準
es6對這個屬性的行為做出了一些修改,如果將一個匿名函數賦值給一個變量,es5的name屬性會返回空字符串,而es6的name屬性會返回實際的函數名
var fun=function(){}
fun.name;//es5 ""
fun.name;//es6 fun
如果將一個具名函數賦值給一個變量,則es5和es6的name屬性都返回這個具名函數原本的名字
var bar=function baz(){}
bar.name;//es5 baz
bar.name;//es6 baz
Function構造函數返回的函數實例,name屬性的值是“anonymous”
(new Function).name;//anonymous
bind返回的函數,name屬性值會加上“bound”前綴
function foo(){}
foo.bind({}).name;//bound foo
(function (){}).bind({}).name;//bound
prototype屬性
每一個函數都有一個prototype屬性,這個屬性指向一個對象的引用,這個對象稱作原型對象。每一個函數都包含不同的原型對象。將函數用作構造函數時,新創建的對象會從原型對象上繼承屬性
function fn(){}
var obj=new fn;
fn.prototype.a=1;
console.log(obj.a);//1
函數方法
apply()和call()
每個函數都包含兩個非繼承而來的方法,apply()和call().這兩個方法的用途都是在特定的作用域中調用函數,實際上等于函數體內this對象的值。
要想以函數對象o的方法來調用函數f(),可以這樣使用call()和apply()
f.call(o)
f.apply(o)
假設o中不存在m方法,則等價于
o.m = f; //將f存儲為o的臨時方法
o.m(); //調用它,不傳入參數
delete o.m; //將臨時方法刪除
下面是一個實際的例子
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)等價于
o.sayColor=sayColor;
o.sayColor();//blue
delete o.sayColor;
apply()方法接收兩個參數:一個是在其中運行函數的作用域(或者可以說是要調用函數的母對象,它是調用上下文,在函數體內通過this來獲得對他的引用),另一個是參數數組。其中,第二個參數可以是array的實例,也可以是arguments對象
function sum(num1,num2){
return num1+num2;
}
//因為運行函數的作用域是全局作用域,所以this代表的是window對象
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()方法的作用相同,它們的區別僅僅在于接收參數的方式不同,對于call方法而言,第一個參數是this值沒有變化,變化的是其余參數都直接傳遞給函數。換句話說,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來
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(),完全取決于采取哪種函數傳遞參數的方式最方便。如果打算直接傳入arguments對象,或者包含函數中先接收到的也是一個數組,那么使用apply()肯定更方便,否則,選擇call()可能更合適
在非嚴格模式下,使用函數的call()或apply()方法時,null或undefined值會被轉換為全局對象。而在嚴格模式下,函數的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
應用
1.調用對象的原生方法
var obj={};
obj.hasOwnProperty("toString");//false
obj.hasOwnProperty=function(){
return true;
}
obj.hasOwnProperty("toString");//true
Object.prototype.hasOwnProperty.call(obj,"toString");false
2.找出數組中的最大值
js不提供找出數組最大元素的函數,結合使用apply方法和math.max方法,就可以返回數組的最大元素
var a=[1,33,2,4,5,6];
Math.max.apply(null,a)
3.將數組對象轉換成真正的數組
Array.prototype.slice.apply({0:1,length:1})//[1]
或者
[].prototype.slice.apply({0:1,length:1})
4.將一個數組的值push到另一個數組中
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.綁定回調函數的對象
由于apply方法或者call方法不僅綁定函數執行時所在的對象,還會立即執行函數,因此不得不把綁定語句寫在函數體內,更簡潔的寫法是采用下面的bind方法
var o={};
o.f=function(){
console.log(this===o)
}
var f=function(){
o.f.apply(o)
}
bind()方法
bind()是es5新增的方法,這個方法的主要作用是將函數綁定到某個對象上
當在函數f()上調用bind()方法并傳入一個對象o作為參數,這個方法將返回一個新的對象。以函數調用的方式調用新的函數將會把原始的函數f()當作o的方法調用,傳入新函數的任何實參都將傳入原始函數
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方法不僅是將函數綁定到一個對象上,它還附帶一些其他應用:除了第一個實參外,傳入bind的實參也會綁定到this,這個附帶的應用是一種常見的函數式編程及時,稱柯里化
var sum=function(x,y){
return x+y;
}
var succ=sum.bind(null,1);
succ(2);//3,x綁定到1,并傳入2作為實參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()
函數的toString()實例方法返回函數代碼的字符串,而靜態的toString()方法返回一個類似’[native code]’的字符串作為函數體
function test(){
alert(1)
}
test.toString()
Function.toString()
toLocalString()
toLocalString()方法和toString()方法返回的結果相同
function test(){
alert(1);//test
}
test.toLocaleString();/*"function test(){
alert(1);//test
}"*/
Function.toLocaleString();//"function Function() { [native code] }"
valueOf()
函數的valueOf()方法返回函數本身
function test(){
alert(1);//test
}
test.valueOf();/*function test(){
alert(1);//test
}*/
typeof test.valueOf();//'function'
Function.valueOf();//Function() { [native code] }