建立自定义对象的最简单方式就是建立一个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); };