//JS該如何檢測數據的類型呢?編程
//使用關鍵字: typeof 數組
//輸出結果依次爲:'number','string','boolean'.閉包
1 console.log(typeof 17); 2 console.log(typeof '17'); 3 console.log(typeof true);
//輸出結果依次爲:'object','undefined'app
1 console.log(typeof null); 2 console.log(typeof undefined);
//可知:null 是object類型。函數
//輸出結果依次爲:'number','object'. 能夠設想一下String('17'),new String('17');優化
1 console.log(typeof Number(17)); 2 console.log(typeof new Number(17));
//輸出結果依次爲:'string','object'this
1 console.log(typeof String('17')); 2 console.log(typeof new String('17'));
//同理:'boolean','object'。spa
1 console.log(typeof Boolean(true)); 2 console.log(typeof new Boolean(true));
//Why ?
//使用new 關鍵字是構造新的對象。new Number()是構建一個number對象。
//new Number(17) 是17 的包裝類型對象。而單純的Number(17)是強制轉換,是轉型函數。
//使用new調用基本包裝類型的構建函數與直接調用同名的轉型函數是不同的。
//再看下面的實例,依次輸出:false,true,falseprototype
1 console.log((17) instanceof Number); 2 console.log(new Number(17) instanceof Number); 3 console.log(Number(17) instanceof Number);
//在Java編程中,咱們都知道針對原始類型,Java API都提供對應包裝對象。
//那麼JS編程中,JS針對三種原始類型也提供了對應的包裝對象:Number,String,Boolean.
//同理適用於String,Boolean. 指針
//接着往下看。
//輸出結果爲:'object','object','function'
1 console.log(typeof []); 2 console.log(typeof {}); 3 console.log(typeof function(){});
//'object',陰魂不散,真使人討厭。
//問題來了,該如何準確的判斷這些'object'呢?
//先介紹下call,apply 方法。
//在JS中,函數是一等公民。便可構建對象,又可做爲值來使用。
//聲明函數很簡單
1 function f1(){ 2 console.log("聲明函數使用關鍵字function"); 3 } 4 function f2(num1,num2){ 5 console.log("這是帶二個參數的函數。"+num1+num2); 6 } 7 function f3(who){ 8 console.log("hello "+who); 9 return "我是有返回值的函數"; 10 }
//調用函數至關簡單:一對圓括號,若是須要參數就附帶上參數。
f1();f2(1,2);console.info(f3('china'));
//關於函數表達式,函數做爲值,在後面講閉包時在講。
//關於函數參數
1 function test(num1,num2){ 2 console.log(num1); 3 num1=10; 4 console.log(arguments[0]+" "+num2); 5 arguments[0]=2; 6 console.log(num1+" "+num2); 7 console.log(arguments instanceof Array); 8 console.log(arguments.toString()); 9 } 10 test(0,1);
//在JS中,系統有一個叫做:arguments的東東進行維護函數的參數。argument不是Array的實例。
//可是arguments擁有相似數組的特性:好比可使用方括號語法訪問參數的元素,
//擁有length屬性獲取參數的個數。
1 function f4(arg1,arg2,arg3){ 2 console.log(arguments.length); 3 for(var index=0,length=arguments.length;index<length;index++){ 4 console.log(arguments[index]); 5 } 6 } 7 f4('中國',"福建"); 8 f4('I ','am ','dylan'); 9 f4('I ','am ','dylan','!!!');
//正是由於有arguments類數組管理參數,因此在參數傳遞時JS不會去考慮參數的個數。
//同時請觀察test函數,能夠發現num1與argument[0]值不只相等,並且是同步改變的。
//在傳統面向對象編程中,構建函數是能夠重載的,可是在JS中沒有重載。
//function 也是對象。
console.log(function(){} instanceof Object);
//擴展一下,既然function是對象,那麼函數名就是指向函數的指針了。
//既然是對象就必有相應的屬性與方法,function擁有length,prototype屬性(此屬性後續再講)
//擁有apply,call方法。
1 function testLength1(){ 2 console.log("testLength1.length="+testLength1.length); 3 console.log("沒有參數,所以length爲0。"); 4 console.log("arguments.callee.length="+arguments.callee.length); 5 } 6 function testLength2(name){ 7 console.log("testLength2.length="+testLength2.length); 8 console.log("有一個參數,參數長度爲1"); 9 console.log("arguments.callee.length="+arguments.callee.length); 10 console.log("arguments.length="+arguments.length); 11 } 12 13 testLength1(); 14 testLength2(); //注意 15 testLength2("dylan"); 16 console.info(testLength1.length); 17 console.info(testLength2.length);
//一目瞭然了吧:length屬性表示函數但願接收的命名參數的個數。
//arguments是個類數組,它主要做用是管理函數的參數。
//arguments.callee表明當前函數名,在本例中就是:testLenght2.
//使用argument.callee在遞歸中頗有幫忙。感興趣同窗能夠去探索一下。
//函數的length屬性與函數調用時實際接收到的參數值並不必定相等。
//每一個function都有二個方法:apply,call. 做用是執行指定函數(對象)的上下文。
1 var o1 ={ 2 name: 'dylan', 3 getName: function(){ 4 return this.name; 5 }, 6 setName: function(greet,name){ 8 return greet+" , "+ name 9 } 10 } 11 12 var o2 ={ 13 name: 'bady', 14 getName: function(){ 15 return this.name; 16 } 18 } 19 //var o3={name:'hello'}; 20 var o3={};
//調用o1的getName的方法,指定的上下文對象是o3,而o3沒有name屬性,因此返回undefined.
console.log(o1.getName.call(o3));
//調用o1的getName的方法,此的上下文對象是o2。因此返回bady.
console.log(o1.getName.call(o2));
//call與apply區分不大,主要在於apply 參數爲數組。
1 console.log(o1.setName.call(o2,'Hi',' tony ')); 2 console.log(o1.setName.apply(o2,['Hi',' fred '])); 3 //console.log(o1.setName.apply(o2,'Hi',' fred '));
//ok,說了這麼多,如今迴歸typeof
1 function toType(type){ 2 if(arguments.length==0){ 3 return ; 4 } 5 if((typeof type)!=='object'){ 6 return typeof type; 7 } 8 9 //return ({}).toString.call(type); 10 return ({}).toString.call(type).match(/\s(\w+)/)[1]; 11 } 12 console.log(toType([12])); 13 console.log(toType({})); 14 console.log(toType(function(){})); 15 console.log(toType(17)); 16 console.log(toType('17')); 17 console.log(toType(false)); 18 console.log(toType(new Number(17))); 19 console.log(toType(null)); 20 console.log(toType(undefined)); 21 console.log(toType(String("dylan")));
//toType還能夠這樣優化。
//return ({}).toString.call(type).match(/\s(\w+)/)[1];
//最後還能夠調用toLowerCase方法。
//return ({}).toString.call(type).match(/\s(\w+)/)[1].toLowerCase();