”JavaScript 祕密花園“ 學習筆記 :

前言 :

JS-Garden總結筆記
文章鏈接


1. 對象

1 .除了null和undefined外,所有變量都可當做對象使用;eg:

1..toString();
false.toString();
var func = function(){alert('test')};
func .toString();

2 . 對象屬性的訪問方式(兩種:對象.屬性,對象[‘屬性’]),屬性名爲JS關鍵字或存在空格,後者同樣有效;

3 . 刪除對象屬性的唯一方法 delete,undefined 和 null不能刪除屬性,只是移除值

delete(obj.pro);  

4 .原型 (父代的顯式原型屬性存在於子代的隱式原型中(繼承))

/*1.創建對象Func_01,並自定義原型中的屬性*/
	function Func_01() {
	  this.value = 42;
	}
	Func_01.prototype = {
	  method: function() {}
	};
    /*2.創建對象Func_02,並設置其prototype屬性爲Func_01的實例*/
    function Func_02(){};
    Func_02.prototype = new Func_01();
    Func_02.prototype.new_prop = 'new property';
    
    /*3.Func_02 繼承Object中的constructor,將constructor更改爲Func_02*/
    Func_02.prototype.constructor = Func_02;
	/*Func_02的顯式原型中包含value,new_prop和constructor屬性,
	隱式原型中則是繼承了Func_01的顯式原型prototype的屬性,如:method*/
	
	/*4.創建Func_02實例,觀察其原型鏈*/
	var target = new Func_02();
	/*target的顯示原型prototype 爲空,
	但其隱式原型_proto_繼承了Func_02和Func_01的顯式屬性prototype*/

5 . hasOwnProperty(),判斷對象的自定義屬性,非原型鏈上的屬性,檢查對象屬性的唯一可用方法

var func01(){};
func01.prototype.name = 'ztx';  //在func01原型中定義name屬性
var test = new func01();
test.selfPrototype = undefined; //自定義屬性

test.name;  //'ztx'
test.selfPrototype;  //undefined
test.hasOwnProperty('name');  //false 原型鏈上的屬性
test.hasOwnProperty('selfPrototype');  //true 自定義屬性

2. 函數

1.普通函數聲明

func01(); //js引擎將所有變量聲明放入global作用域,func01() 執行時已被聲明並創建;

function func01(){
  alert('this is func01');
}

2.匿名函數賦值表達式

func02; //undefined ,此時func02被聲明,但未定義,所以是缺省值
func02(); //未定義類型,賦值操作在運行到該行時才執行,所以不是function 類型,即 typeError :類型錯誤
var func02 = function(){
alert('this is func02');
}
func02(); //正確位置

3.命名函數賦值表達式`

var foo = function bar() {
    bar(); // 正常運行,函數名在函數內部總是可見
}
bar(); // 出錯:ReferenceError,bar()已經賦值給了foo()函數;

4.this關鍵字: 五種不同的情況,this指向各不同;

五種情況 指向
全局範圍內 this指向全局對象
函數調用時 全局作用域中,定義函數並調用時,fun();等同於this.fun();this指向全局
方法調用時 this指向調用該方法的對象;function show(){return this.name;}
調用構造函數時 在函數內部,this指向新創建的對象
顯式設置時 obj.call()/obj.apply();當函數中指定對象後,默認的this則被顯式設置了

* 注: JavaScript中函數和方法的區別

// ******************構造函數(見第六點)******************
function objA(name,age){
  if(name!=null&&age!=null){
    this.name = name; //this 指向新創建的對象
    this.age = age;
  }else{
    this.name = "wyy";
    this.age = 20;
  }
}
objA.prototype.showName = function(){
  alert(this.name);
}

var obj01 = new objA();
obj01.name;
obj01.age;
obj01.showName();
objA.prototype.showAge = function(){
  alert(this.age);
}
obj01.showAge();//20, 對象objA新增新的方法後,重新生成實例

var obj02 = new objA('ztx',24);
obj02.name;
obj02.age;
obj02.showName();
obj02.showAge();

//******************顯式設置this******************
var test = 'wyy';
var obj3 = {
  test:'ztx'
}
function show(){
  alert(this.test);
}
show();
show.call(obj3);//this 由window被顯式設置爲obj3

//******************將方法進行表達式賦值後,this的動態變化******************
var obj3 ={name:'obj3'};
var foo = {};
foo.method = function(){
  var obj1 = this; //this指向 foo,賦值表達式之後,指向window
  function test(){
    obj1;
    var obj2 = this; //this 指向window,調用call方法後,指向obj3
  };
  test.call(obj3);
};

foo.method();//this 指向 方法的調用者:foo

var test = foo.method;
test(); //this 指向window

#####5 .閉包與引用

  1. 閉包:在當前作用域中,存在着對外部作用域變量的引用,外部變量的值在函數執行之後也不會被內存回收。當前作用域總是能夠訪問外部作用域變量;

  2. 通過函數創建閉包,因爲 函數是JS中唯一擁有自身作用域的結構,沒有塊級作用域

    //demo_01: 
    //自執行匿名函數中傳參i,從而獲得外部作用域變量i的引用
    for(var i=0;i<10;i++){
               (function(e){
                   setTimeout(function(){
                       console.log(e);
                   },1000);
               })(i);
           }
    
  3. 作用域中的變量提升 ---- hoisting (參考博客園JackWang-CUMT的博客,thanks

    作用域中的所有變量的聲明(不包括賦值),都會被置頂。

//自運行匿名函數中的 var myvar ='內部變量值',在編譯解釋的時候會被提升到該函數的頂部,即
//var myvar = '變量值'; 

//(function() {
//var myvar;
// console.log(myvar); // 所以此處爲 undefined
// var myvar = ‘內部變量值’;
//})();

var myvar = ‘變量值’;
(function() {
console.log(myvar); // undefined
var myvar = ‘內部變量值’;
})();

#####6.構造函數
1.

  1. 通過 new 關鍵字調用的函數都被認爲是構造函數;
  2. 當構造函數沒有顯式return時,則隱式return新創建的對象,即有return的構造函數,得到的是返回的對象,沒有return的構造函數,得到的是創建的對象;

3.數組相關

  1. 使用普通for循環來遍歷數組,for in 遍歷可能導致錯誤,並降低性能;

  2. 使用普通for循環是,提倡緩存數組的長度,即:

for(var i=0, len=array.length;i<l,i++){}
  1. Array 構造函數,推薦使用數組字面語法,即:[ ] 來新建數組,使用構造函數 new Array() 創建數組時,當Array()中傳入一個數字 參數時,將設置數組的length屬性,數組未被創建;

  2. 修改array.length=10屬性,減小array.length=5則對數組進行截斷,將array.length=10增加爲原長度後,數組length屬性改變,其他不變,數組沒有新增索引,

    array[5]~array[9]; //undefined
    5~9 in array; //false
    
    array[5] = undefined; //自定義新索引
    5 in array ; //true
    

4.類型

#####1.比較

  1. 等於操作符 ==嚴格等於操作符 === ,判斷是否相等時應使用後者,前者在比較時進行強制類型轉換,後者則不會,如需轉換,應顯式轉換;
  2. 比較運算中,若有一個操作數爲對象,則比較的不是值是否相等,而是判斷是否是同一個對象。
  3. 使用Object.prototype.toString 來檢測一個對象的類型
2.typeof / instanceof 操作符

5.核心

1.eval()執行時的作用域:(不要使用eval)

​ 當前作用域:eval() 被直接調用,且調用函數就是eval自身

​ 全局作用域: 以上除外

2.undefined 和 null

​ 1.undefined 這個變量不是常量,不是關鍵字,是一個可以被輕易覆蓋的值;

​ 2.Null,另一種數據類型

3.JS分號自動插入,對於沒有分號的代碼,分號自動插入有時會改變代碼行爲或編譯出錯。

6.其他

  1. JS引擎的計時策略和單線程運行模式,無法確保setTimeout()被準時調用;

  2. 使用setTimeout / setInterval 函數時,第一參數不用使用字符串,使用匿名函數;

  3. 在調用定時器函數時,使用字符串形式時,不要向回調函數中傳參

    setTimeout('foo(1,2,3)',1000);//不推薦
    
    setTimeout(function(){ //使用匿名函數實現上述功能
      foo(1,2,3);
    },1000);
    

Version_01 17/09/14 待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章