javascript物件導向程式設計(一),javascript物件導向

來源:互聯網
上載者:User

javascript物件導向程式設計(一),javascript物件導向

注釋裡講解的十分細緻了,這裡就不多廢話了,直接上代碼:

<script type="text/javascript">  //ECMA-262把對象定義為:“無序屬性的 集合,其屬性可以包含基本值、對象或者函數”  //理解對象,最簡單的方式就是通過建立一個Object的執行個體,然後為它添加屬性和方法  var person = new Object();  person.name = "Xulei";  person.age = "23";  person.job = "前端工程師";  person.sayName = function () {   alert(this.name);  }  //還可以這樣寫  var person = {   name: "xulei",   age: 23,   job: "前端工程",   sayName: function () {    alert(this.name)   }  }  //一、屬性類型:資料屬性和訪問其屬性  //1、資料屬性,有4個描述其行為的特性  //[Configurable]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性,預設值為true  //[Enumerable]:表示能否通過for-in返回屬性,預設值為true  //[Writable]:表示能否修改屬性,預設值為true  //[Value]:包含這個屬性的資料值。預設值為undefined  var person = {   name: "xulei"  }  //這裡建立了一個person對象,value值就是“xulei”  //要修改屬性的預設特性,必須使用ECMAScript5的Object.defineProperty(屬性所在的對象,屬性的名字,描述符對象)  //描述符對象必須是configurable、enumerable、writable、value  var peron = {}  Object.defineProperty(peron, "name", {   writable: false,//屬性不能被修改   value: "徐磊-xulei"  });  alert(peron.name);//徐磊-xulei  peron.name = "徐磊";  alert(peron.name);//徐磊-xulei  //以上操作在非strict 模式下賦值操作會被忽略,如果在strict 模式下會拋出異常  //一旦把屬性定義為不可配置的就不能把它變回可配置的了。  //在多數情況下都沒有必要利用Object.defineProperty()方法提供的這些進階功能。但是對理解javascript非常有用。  //建議讀者不要在ie8上使用此方法。  //2、訪問其屬性,有4個特性  //[Configurable]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性,預設值為true  //[Enumerable]:表示能否通過for-in返回屬性,預設值為true  //[Get]:在讀取時調用的函數 預設值undefined  //[Set]:在寫入屬性時調用的函數 預設值Undefined  var book={   _year:2004,   edition:1  }  Object.defineProperty(book,"year",{   get:function(){    return this._year;   },   set:function(value){    if(value>2004){     this._year=value;     this.edition +=value-2004;    }   }  });  book.year=2005;  alert(book.edition);//2  //建立對象  //1、將建構函式當做函數  function Person(name,age,job) {   this.name=name;   this.age=age;   this.job=job;   this.sayName=function(){    alert(this.name);   }  }  //當做建構函式使用  var person=new Person("xulei",23,"software");  person.sayName();  //作為普通函數使用  Person("xulei2",23,"job2");//添加到window中  window.sayName();  //在另一個對象的範圍中調用  var o=new Object();  Person.call(o,"xulei3",23,"job3");  o.sayName(); </script>

再來一段:

<script type="text/javascript">    //1、理解原型對象    //2、原型與in操作符    //3、更簡單的原型文法    //4、原型的動態性    //5、原生對象原型    //6、原型對象的問題    //1、無論什麼時候,只要建立了一個函數,就會根據一組特定的規則,為該函數建立一個prototype屬性,該屬性指向函數的原型對象    //在預設情況下,所有的原型對象都會自動獲得一個constructor(建構函式)屬性,這個屬性包含一個指向prototype屬性所在函數的指標    //如    function Person(){    }    //Person.prototype.constructor 指向Person    //建立了自訂的建構函式之後,其原型對象預設只會取得constructor屬性,至於其他方法則都是從Object繼承而來    //當調用函數的建立一個新執行個體之後,該執行個體的內部包含一個指標(內部屬性)指向建構函式的原型對象    //在Firefox、safari、chrome在每個對象上都支援一個屬性_proto_訪問    var p1=new Person();    alert(Person.prototype.isPrototypeOf(p1))    alert(Object.getPrototypeOf(p1)==Person.prototype)    //雖然可以通過對象執行個體訪問儲存在原型中的值,但卻不能通過對象執行個體重寫原型中的值。如果我們在執行個體中添加了一個屬性    //而該屬性的名稱與原型的中的執行個體同名,那我們就在執行個體中建立該屬性,該屬性將會屏蔽原型中的那個屬性。eg:    function Person() {    }    Person.prototype.name="amber";    Person.prototype.age=23;    Person.prototype.job="software engineer";    Person.prototype.sayName=function(){      alert(this.name)    }    var person1=new Person();    var person2=new Person();    person1.name="amber.Xu";    alert(person1.name);//amber.xu --來自執行個體    alert(person2.name);//amber --來自原型    delete person1.name;    alert(person1.name);//amber --來自原型    //使用hasOwnProperty()方法可以檢測一個屬性是存在於執行個體中還是存在於原型中,這個方法(從Object繼承而來)    //只在給定屬性存在於對象執行個體中時,才會返回true    function Person() {    }    Person.prototype.name="amber";    Person.prototype.age=23;    Person.prototype.job="software engineer";    Person.prototype.sayName=function(){      alert(this.name)    }    var person1=new Person();    var person2=new Person();    alert(person1.hasOwnProperty("name"));//false 來自執行個體    alert(person2.hasOwnProperty("name"));//false 來自執行個體    person1.name="amber.xu";    alert(person1.name);    alert(person1.hasOwnProperty("name"));//true 來自執行個體    delete person1.name;    alert(person1.name);    alert(person1.hasOwnProperty("name"));//false 來自原型    //2、原型與in操作符    //in 有兩種使用方式,一個是的單獨使用和在for-in 中使用。在單獨使用時,in操作符會在對象能夠訪問給定屬性時返回true    //無論該屬性時來自原型還是執行個體    function Person() {    }    Person.prototype.name="amber";    Person.prototype.age=23;    Person.prototype.job="software engineer";    Person.prototype.sayName=function(){      alert(this.name)    }    var person1=new Person();    var person2=new Person();    alert("name" in person1);//true 來自原型    alert("name" in person2);//true 來自原型    alert("height" in person1);//false    //這樣就可以封裝一個函數(給定屬性是否是來給定對象的原型)    function hasPrototypeProperty(object,name){      return !object.hasOwnProperty(name) && (name in object);    }    alert("----------------------------------");    alert(hasPrototypeProperty(person1,"name"));//true    person1.name="張三";    alert(hasPrototypeProperty(person1,"name"));//false    //使用for-in 返回的是所有能夠通過對象訪問、可枚舉的屬性,其中既包含原型屬性也包含執行個體屬性。    //屏蔽了原型中不可枚舉屬性(將Enumerable標記為false的屬性)的執行個體屬性也會在for-in中返回    //ie早期版本總中有一個bug:屏蔽了原型中不可枚舉屬性的執行個體屬性也不會在for-in中返回    //eg:    var o={      toString:function(){        return "my object";      }    };    for(var prop in o){      if(prop=="toString"){        alert("找到了");//在ie早期版本中不會顯示      }    }    //要取得對象上所有可枚舉的屬性,可以使用ECMAScript5的Object.keys()方法。接受一個對象作為參數,    //包含所有可枚舉屬性的字串數組    function Person() {    }    Person.prototype.name="amber";    Person.prototype.age=23;    Person.prototype.job="software engineer";    Person.prototype.sayName=function(){      alert(this.name)    }    var person1=new Person();    var person2=new Person();    var keys=Object.keys(Person.prototype);    alert(keys)    person1.name="amber.Xu";    person1.age=23;    var keys=Object.keys(person1);    alert(keys)    alert("-----------------------------------------")    //如果想要得到所有的執行個體屬性不管他是否可以枚舉,都可以使用    alert(Object.getOwnPropertyNames(person1));    alert(Object.getOwnPropertyNames(Person.prototype));    alert("更簡單的原型文法-----------------------------------------")    //3、更簡單的原型文法    function Person() {    }    Person.prototype={      name:"AMBER",      age:23,      job:"software",      sayName:function(){        alert(this.name)      }    }    //這樣寫之後constructor屬性不再指向Person函數,而是指向Object建構函式。    //儘管通過instanceof操作符還能返回正確的結果,但是通過constructor已經無法確定對象的類型了,eg:    var friend=new Person();    alert(friend instanceof Person)//true    alert(friend instanceof Object)//true    alert(friend.constructor==Person);//false    alert(friend.constructor==Object);//true    //如果constructor對你真的很重要,可以向下面一樣設定成適當的值    function Person() {    }    Person.prototype={      constructor:Person,      name:"AMBER",      age:23,      job:"software",      sayName:function(){        alert(this.name)      }    }    var friend=new Person();    alert("手動設定constructor-----------------------------------------")    alert(friend.constructor==Person);//true    //這種手動的添加了constructor會使constructor變成可枚舉的元(原生的constructor屬性時不可枚舉的)。    //這種情況下就可以使用    Object.defineProperty(Person.prototype,"constructor",{      enumerable:false,      value:Person    });    //原型的動態性    var friend=new Person();    Person.prototype.sayHi=function(){      alert("Hi");    }    friend.sayHi();//Hi (正常執行)    //因為執行個體和原型之間是鬆散的串連關係,執行個體與原型之間的串連只不過是一個指標,而非副本    //當我們調用sayHi()方法時,首先會在執行個體中搜尋名為sayHi的方法,在沒找到的情況下會搜尋原型。    //但是,如果是重寫整個原型對象,那麼情況就不一樣了。    //我們知道,調用建構函式時會為執行個體添加一個指向最初原型的Prototype指標,而把原型修改為另一個對象就等於切斷了建構函式與最初原型之間的聯絡。    //請記住:執行個體中的指標僅指向原型,而不指向建構函式。eg:    function A(){}    var a1=new A();    A.prototype={      constructor:A,      name:"AMBER",      age:23,      job:"software",      sayName:function(){        alert(this.name)      }    }    alert("ERROR-------------------------------------");    alert(a1.sayName());    //我們建立了一個A的執行個體,然後又重寫了其原型對象,然後在調用a1.sayName()發生了錯誤,因為a指向的原型中不包含以該名字命名的屬性/方法    //原生對象的原型    //原型模式的重要性不僅體現在建立自訂類型方面。就連所有的原生的參考型別,都是採用這種模式建立的。所有的原生參考型別    //都在其建構函式的原型上定義的方法 eg:    alert(typeof Array.prototype.sort);//function    alert(typeof String.prototype.substring);//function    //不僅可以在原生對象的原型取得雖有預設方法的引用,而且可以定義新的方法    //為String類型添加一個startsWith()的方法    String.prototype.startsWith=function(text){      return this.indexOf(text) == 0;    };    var msg="Hello";    alert(msg.startsWith("H"));    //我們並不建議這樣做。    alert("原型對象的問題");    //6、原型對象的問題 執行個體    function Ques() {    }    Ques.prototype={      constructor:Ques,      name:"amber",      age:23,      job:"IT",      friends:["張三","李四"],//參考型別      sayName:function(){        alert(this.name)      }    };    var q1=new Ques();    var q2=new Ques();    q1.friends.push("王五");    alert(q1.friends);//    alert(q2.friends);//    alert(q1.friends===q2.friends);  //相信大家已經看到了問題,當我建立了兩個執行個體q1、q2,當我為q1的“朋友”添加了“王五”之後,q2的”朋友“也有了三個張三、李四、王五  //那是因為數組存在於Ques.prototype上,而非q1上。所以出現了如上結果。  //而正是這個問題,我們很少看到有人單獨使用原型模式的原因所在。  </script>

本文就先到這裡了,後續我們再繼續討論javascript物件導向程式設計,希望大家能夠喜歡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.