建立自定義對象的最簡單方式就是建立一個Object的實例,而後再爲它添加屬性和方法javascript
var person=new Object(); person.name="Nicholas"; person.age=20; person.job="Software Engineer"; person.sayName=function(){ alert(this.name) }
對象字面量稱爲建立這種對象的首選方式java
var person={ name:"Nicholas", age:20, job:"Software Engineer", sayName:function(){ alert(this.name); } };
兩種屬性函數
數據屬性,能夠讀取和寫入值,有四個描述其行爲的特性測試
要修改屬性默認的特性,使用Object.definePropery()方法,這個方法接收三個參數:屬性所在的對象、屬性的名字和一個描述符對象。this
var person={}; Object.definePropery(person,"name",{ writable:false, value:"Nicholas" }); alert(person.name);//"Nicholas" person.name="Greg"; alert(person.name);//"Nicholas"
訪問器屬性,包含一對getter和setter函數。在讀取訪問器屬性的時候,會調用getter函數,這個函數負責返回有效的值。在寫入訪問器屬性的時候,會調用setter函數並傳入新值,這個函數負責決定如何處理數據。spa
Object.defineProperties()方法能夠經過描述符一次定義多個屬性,這個方法接收兩個對象參數,一個對象是要添加和修改其屬性的對象,第二個對象的屬性與第一個對象中要添加或修改的屬性一一對應prototype
var book = {}; Object.defineProperties(book, { _year: { value: 2004 }, edition: { value: 1 }, year: { get: function(){ return this._year; }, set: function(newValue){ if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } } });
Object.getOwnPropertyDescription()方法,能夠取得給定屬性的描述符,這個方法接收兩個參數,屬性所在的對象和要讀取其描述符的屬性名稱設計
var book = {}; Object.defineProperties(book, { _year: { value: 2004 }, edition: { value: 1 }, year: { get: function(){ return this._year; }, set: function(newValue){ if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } } }); var descriptor = Object.getOwnPropertyDescriptor(book, "_year"); alert(descriptor.value); //2004 alert(descriptor.configurable); //false alert(typeof descriptor.get); //"undefined" var descriptor = Object.getOwnPropertyDescriptor(book, "year"); alert(descriptor.value); //undefined alert(descriptor.enumerable); //false alert(typeof descriptor.get); //"function"
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var person1 = createPerson("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor");
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor");
只要經過new操做符來調用,那它就能夠做爲構造函數指針
// 看成構造函數使用 var person = new Person("Nicholas", 29, "Software Engineer"); person.sayName(); //"Nicholas" // 做爲普通函數調用 Person("Greg", 27, "Doctor"); // 添加到 window window.sayName(); //"Greg" // 在另外一個對象的做用域中調用 var o = new Object(); Person.call(o, "Kristen", 25, "Nurse"); o.sayName(); //"Kristen"
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); person1.sayName(); //"Nicholas" var person2 = new Person(); person2.sayName(); //"Nicholas" alert(person1.sayName == person2.sayName); //true
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } Person.prototype = { constructor : Person, sayName : function(){ alert(this.name); } } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Count,Van" alert(person2.friends); //"Shelby,Count" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true
function Person(name, age, job){ //屬性 this.name = name; this.age = age; this.job = job; // 方法 if (typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); }; } } var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName();
function Person(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName(); //"Nicholas"
function Person(name, age, job){ //建立要返回的對象 var o = new Object(); //能夠在這裏定義私有變量和函數 //添加方法 o.sayName = function(){ alert(name); }; //返回對象 return o; }
能夠經過兩種方式來肯定原型和實例之間的關係,第一種方式是使用instanceof操做符,只要這個操做符來測試實例與原型鏈中出現過的構造函數,結果就會返回truecode
alert(instance instanceof Object); //true alert(instance instanceof SuperType); //true alert(instance instanceof SubType); //true
第二種方式是使用isPrototypeOf()方法,只要是原型鏈中出現過的原型,均可以說是原型鏈所派生的實例的原型,所以isPrototypeOf()方法也會返回true
alert(Object.prototype.isPrototypeOf(instance)); //true alert(SuperType.prototype.isPrototypeOf(instance)); //true alert(SubType.prototype.isPrototypeOf(instance)); //true
function SuperType(){ this.colors = ["red", "blue", "green"]; } function SubType(){ // 繼承了 SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); alert(instance2.colors); //"red,blue,green"
對於原型鏈而言,借用構造函數有一個很大的優點,便可以在子類型構造函數中向超類型構造函數傳遞參數
function SuperType(name){ this.name = name; } function SubType(){ //繼承了 SuperType,同時還傳遞了參數 SuperType.call(this, "Nicholas"); //實例屬性 this.age = 29; } var instance = new SubType(); alert(instance.name); //"Nicholas"; alert(instance.age); //29
指的是將原型鏈和借用構造函數的技術組合到一塊
function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ //繼承屬性 SuperType.call(this, name); this.age = age; } //繼承方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); }; var instance1 = new SubType("Nicholas", 29); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Nicholas"; instance1.sayAge(); //29 var instance2 = new SubType("Greg", 27); alert(instance2.colors); //"red,blue,green" instance2.sayName(); //"Greg"; instance2.sayAge(); //27
var person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; var anotherPerson = Object.create(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = Object.create(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
思路和構造函數和工廠模式相似,即建立一個僅用於封裝繼承過程的函數,函數在內部以某種方式來加強對象
function createAnother(original){ var clone = object(original); //經過調用函數建立一個新對象 clone.sayHi = function(){ //以某種方式來加強這個對象 alert("hi"); }; return clone; //返回這個對象 } var person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi(); //"hi"
不管什麼狀況下都會調用兩次超類型構造函數,一次是在建立子類型原型的時候,另外一次實在子類型構造函數內部
function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ SuperType.call(this, name); // 第二次調用 SuperType() this.age = age; } SubType.prototype = new SuperType(); // 第一次調用 SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); };