1. 程式人生 > >javascript的對象問題及總結

javascript的對象問題及總結

arr prevent 是什麽 basic 所有 type spro dde pan

一 js中的對象是什麽?

-- js的對象是一種無序的數據集合,由若幹鍵值對組成(key-value)組成,裏面包含著數據(屬性)和方法(動作),它可以代表js中的所有事物。

- 例如將動物抽象成一類對象,此類對象有著動物中特有的屬性和動作,不同於植物,而動物中又分有豬,狗,雞不同類型的事物對象,這些類型事物對像既有著動物類型的屬性和動作,又有著自身獨特類型的屬性和動作,可以這樣一直細分下去,直到每一種動物的個例,也就是對象的實例了,它不僅具備上層事物共有的屬性和方法,也有著自己獨特個性,是一個獨特的個體。

1-1 js的對象如何創建?

-- 對象可通過對象字面量({}),構造函數(如new Object(),或自定義),Object.create等方式創建。

1-1-1 對象字面量,與new Object()創建對象方式的異同?

相同點:創建的對象在使用上是一致的,var a = {} // 是var a= new Object()的語法糖

不同點:初始化的過程有些區別,new Object()是通過構造函數實例化對象,{ }是直接創建JSON對象,且在初始化時可以直接賦值,相比{ }比較高效

1-1-2 訪問及修改對象的屬性

-- 對象是由鍵值對組成,對象的鍵名又稱屬性(property),都是字符串類型,鍵名符合標識名條件或是數字可省略" ",系統會默認自動轉為對應的字符串,鍵值可以是任意類型,若鍵值是函數,則該屬性又可被稱為方法,像函數般調用。

  • 使用 .[ ] 訪問或修改增添對象的屬性
  • delete刪除屬性
  • in檢查是否屬於自身的屬性
  • Object.keys(obj)查看所有自身可枚舉屬性,Object.getOwnPropertyNames(obj)包括自身不可枚舉的屬性如數組中的"length",都返回屬性名數組
  • for...in 循環遍歷對象本身屬性
  • Object.observe(obj,function(changes))觀察對象屬性變化

1-1-2eg1:對象字面量式創建

  <script>
    //對象字面量式創建
    var obj = {
      name: fermin,
      run: 
function () { alert(run); } }; obj.age = 18; //添加屬性 console.log(obj.age); //18 delete obj.age; //刪除屬性,註意:不能刪除繼承的屬性,會返回false,刪除不存在的屬性不會報錯,且返回true alert(obj.age); // undefined,訪問不存在的屬性返回undefined alert("age" in obj); //false, 註意:in對對象擁有的屬性都返回ture,無論是否是繼承的,無法識別繼承屬性 console.log(Object.keys(obj)); //["name","run"] //Object.keys()返回所有本身屬性名 for (let i in obj) { console.log(i); //name run //for..in 遍歷可enumerable的自身和繼承的屬性,可加obj.hasOwnProperty(i),過濾為自身屬性 } obj.run(); //run //用點號訪問屬性和方法 obj[run](); //run //用[]訪問屬性和方法 alert("toString" in obj); //true
</script>

構造函數:構造函數創建對象是借用Object.create(原型) 來實現。

1-1-2eg2:new Object() 創建 (訪問和修改對象屬性與上述相同)

<script>
    //new Object()創建
    var obj = new Object(); //new可以省略
    obj.name = fermin;
    obj.age = 18;           //添加屬性
    obj.run = function () {
        alert(run);
    };                    //添加屬性
    delete obj.age;   //刪除屬性  //delete只能刪除對象的屬性如:var a=1; delete a  //false
    alert(obj.age);  // undefined,訪問不存在的屬性返回undefined
    alert("age" in obj);//false
    console.log(Object.keys(obj)); //["name","run"] 
    for (let i in obj) {
      console.log(i);  //name run 
    }
    obj.run();      //用點號訪問屬性和方法
    obj[run]();   //用[]訪問屬性和方法 
    alert("toString" in obj);  //true
</script>

1-1-2eg3:自定義構造函數

<script>
    //自定義構造函數
    function Person(name) {
      this.name = name; 
    }
    var obj = new Person("fermin");
    obj.age = 18;
    obj.run = function () {
      alert("run");
    }; //添加屬性
    alert(Object.keys(obj)); //name,age,run
    for (let i in obj) {
      console.log(i); //name age run
    }
    obj.run(); // run
    obj[run](); // run
    alert("toString" in obj); //true
</script>

1-1-2eg4:Object.create(原型) // Object.create(Object.prototype) <==> new Object()

<script>
    //Object.create(原型);
    var obj = Object.create(null); 
    //原型為null,不能繼承Object.prototype中的屬性
    obj.name = fermin;
    obj.age = 18;           //添加屬性
    obj.run = function () {
        alert(run);
    };                    //添加屬性
    delete obj.age;   //刪除屬性
    alert(obj.age);  // undefined,訪問不存在的屬性返回undefined
    alert("age" in obj);//false
    console.log(Object.keys(obj)); //["name","run"] 
    for (let i in obj) {
      console.log(i);  //name run 
    }
    obj.run();      //用點號訪問屬性和方法
    obj[run]();   //用[]訪問屬性和方法 
    alert("toString" in obj);  //false //沒有繼承Object.prototype中的屬性
</script>

1-1-3 new一個對象的過程

var obj = new Function();

  • 創建一個空對象 // var obj = {};
  • 將實例的__proto__屬性指向構造函數的prototype原型 // obj__proto__ = Function.prototype
  • 將構造函數的指針指向實例 // Function.call(obj)

1-1-3eg1:模擬new過程

<script>
function Person(name) { this.name = name; } var obj = Person("fermin"); //不用new obj = {}; obj.__proto__ = Person.prototype; Person.call(obj); obj.age = 18; obj.run = function () { alert("run"); }; //添加屬性 alert(Object.keys(obj)); //name,age,run for (let i in obj) { console.log(i); //name age run } obj.run(); // run obj[run](); // run alert("toString" in obj); //true </script>

1-1-4 函數中this的指向問題

-- this的指向在函數執行時才能確定,總是指向調用該函數的對象

  • 由new調用,指向新建的對象 //在構造函數執行
  • 由call,apply,bind調用,指向綁定的對象 //在強制綁定對象執行
  • 由上下文調用,指向所屬的上下文對象 //在對象屬性執行
  • 沒有所屬對象時,嚴格模式指向undefined或指向全局對象(window或global) //在普通函數執行

1-1-4-eg1:

<script>
    var obj1= {
      a:3,
      b:{
        a:10,
        fn:function(){
          console.log(this.a); //undefined
          console.log(this); //window
        }
      }
    };
    var j = obj1.b.fn;
    j();
    //將fn賦值給變量j時,obj調用fn沒有執行,所以它最終指向的是window,而不是obj
    
    var obj2 = {
      a : A,
      fn: function () {
         console.log(this.a);
      }
    };
    obj2.fn();       //"A"          // this ===obj2
    obj2.fn.call({a: AA}); //"AA" // this === {name: ‘AA‘}
    var fn1 = obj2.fn;
    fn1();           //undefined   //this === window
</script>

二 object對象的方法

2-1 六個實例對象方法,繼承Object.prototype

  • valueOf():返回當前對象對應的值,默認返回對象本身 // var o1 = new Object (); o1.valueOf === o1 //true
  • toString():將對象轉換為字符串形式並返回 // var o2 = {a : 1}; o2.toString() // [object Object] //用Object.prototype.toString.call() 更準確的判斷類型[object,對象類型11種/ Number/ String/ Boolean/ Object/ Array/ Function/ Null/ Undefined/ RegExp/ NaN/ Infinite]
  • toLocalString():將對像轉換為本地對應的字符串並返回
  • hasOwnPropoty():判斷某個屬性是否是自身的非繼承屬性,是的返回true
  • isPrototypeOf(): 判斷當前對象是為另一對象原型,是返回true
  • propertylsEnumerable():判斷某個屬性是否可枚舉

2-2 對象屬性的特征 attributes 對象用Object.getOwnPropertyDescriptor(obj,字符串屬性名)讀取。

  • value:表示該屬性的值,默認undefined
  • writable:表示該屬性的值是否可改,默認true
  • enumerable:表示該屬性名是否可枚舉,默認true //改為false時,for..inObject.keys()JSON.stringify()不遍歷該屬性,可成私密屬性
  • configurable:表述該對像是否可配置,默認true //var 聲明的變量會為false,沒聲明為false,如a=1或this.a=1 //改為false時,writable可從true改為false,當writable為true可改value值,其他值不可修改,不能再用delete刪除該屬性
  • get:表屬性取值函數(getter)默認undefined //定義後,writable不能為true且定義value的值 // get,set為存取器的命令,常使用於某屬性值需依賴對象內部數據場合。 // 利用存取器可以實現數據對象與DOM對象的雙向綁定
  • set:表屬性存值函數(setter)默認underfined //定義後,writable不能為true且定義value的值

2-3 定義對象屬性的attributes對象,下面兩種方法定義後,屬性中的writable,enumerable,configurable的值默認值又都會變為false

  • Object.defineProperty(obj,字符串屬性名,attributesObj)
  • Object.defineProperties(obj,{字符串屬性名: attributesObj,字符串屬性名: attributesObj,...})

2-3-eg1:定義單一attribules屬性

<script>
  var o = Object.defineProperty({}, "p", {
    value: 3,
    writable: false,
    enumerable: true,
    configurable: false
  });
  alert(o.p);  //3
  o.p = 33;
  alert(o.p);  //3  //writable為false,修改不了該屬性的值 
</script>

2-3-eg2:定義多個attributes屬性

<script>
  var o = Object.defineProperties({}, {
    p1: {
      value: 3,
      enumerable: true,
      writable: true, //configurable值沒設定,默認為false
    },
    p2: {
      get: function () {
        return this.p1 + 6;
      },         //有get,就不能直接定義其value值
      enumerable: true,
      configurable: true
    }
  });
  alert(o.p1);  //3
  o.p1 = 4;     //writable,值為true後,可直接用.或[]修改該屬性值,
  alert(o.p1);  //4
  alert(o.p2);  //10 
  Object.defineProperty(o, "p1",{value:33});
  //若再修改p1其它屬性值會報錯,因為一開始configurable為false
  alert(o.p1);  //33 
  //PS:當writable值為false,configurable值為true,只能在defineProperty()中修改
</script>

2-4 對象的拷貝

--將一對象所有屬性拷貝到另一個對象上,有重復的屬性,將被覆蓋

<script>
    var extend = function (to, from) {
      for (var property in from) {
        var descriptor = Object.getOwnPropertyDescriptor(from, property);
        if (descriptor && (!descriptor.writable 
          || !descriptor.enumerable
          || !descriptor.configurable
          || !descriptor.get
          || !desciptor.set)) {
          Object.defineProperty(to, property, descriptor); //都拷貝
        } else {
          to[property] = from[property];  
          //這個else遇存取器定義屬性只拷貝值,適用於descriptor的5個特征都具備
        } 
      }
      return to; 
    };
    var aa = extend({a:1, b:2}, {a:11, bb:22});
    console.log(aa); //{a:11, b:2, bb:22}  
</script>

2-5 控制對象的狀態

  • Object.preventExtensions(obj) //無法再添加新屬性,嚴格模式下添加會拋錯,可用delete刪除現有屬性
  • Object.isExtensible(obj) //沒使用Object.preventExtensions(obj)返回false,使用了返回true
  • Object.seal(obj) //無法添加新屬性,也無法刪除舊屬性,現有屬性的configurable會變為false
  • Object.isSeal(obj) //沒使用Object.seal(obj)返回false,使用了返回true,且isExtensible返回false
  • Object.isFrozen(obj) //是否被凍結,指不可擴展,所有屬性不可配置,所有數據屬性(即沒有getter或setter組件的訪問器的屬性)都是不可寫的。

2-5-eg:

<script>
    var o = new Object();
    Object.preventExtensions(o);
    o.p = 1;
    console.log(o.p); // undefined
    console.log(Object.isExtensible(o)); //false
</script>

javascript的對象問題及總結