面向对象
对象有属性和方法。一般来说属性就是有什么,方法就是做什么。
ECMAScript定义属性分2个类型,数据属性和访问器类型。
- 数据属性有以下4种
- Configurable: 属性能不能删除和修改属性,默认是true
- Enumerable: 属性能不能通过for-in枚举。默认是true
- Writable: 属性能否修改值,默认是true。
- Value: 设置之后读取属性值从这里读,写入属性值从这里写。
要修改属性默认特征要用Object.defineProperty()
var person = {};
Object.defineProperty(person,'name',{
Writable: false,
value:"Tom"
});
alert(person.name);//Tom
person.name = 'Jerry';
alert(person.name);//Tom因为writable为false。
-
访问器属性
访问器属性不包含数据值,包含一对儿getter和setter函数,当读取访问器属性时
调用getter,写入访问器属性时调用setter。
访问器属性包含以下4个特性
1.Configurable: 能否通过delete删除属性,从而重新定义属性。
2.Enumerable:能否使用for-in 枚举
3.get:在读取是调用的函数,默认undefined
4.set:在设置时调用的函数,默认undefined.
用Object.defineProperty()来定义var book = { _year : 2018, edition : 1 }; Object.defineProperty(book,'year',{ get : function(){ return this._year; }, set : function(newValue){ if (newValue > 2010){ this._year = newValue; this.edition += newValue - 2010; } } }); book.year = 2020; alert(book.edition); //11 通过这个办法可以在修改某对象的属性时,做额外的工作。
-
定义多个属性
sanplevar book={}; Object.defineProperties(book,{ _year:{ value:2004 }, edition:{ value:1 }, year:{ get:function(){ return this._year; }, set:function(newValue){ if(newValue > 2010){ this._year=newValue; this.edition += newValue - 2010; } } } });
-
创建对象
书中有多种方法创建对象。最常用的是结合使用构造函数和原型模式
构造函数模式用于定义实例的属性,而原型模式用于定义方法和共享的属性。
结合了2种方法的优点。
sample:
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.friends = ['Tom','Jerry']; } Person.prototype = { constructor : Person, sayName : function(){ alert(this.name); } } var p1 = new Person("Trump",73,"美国总统"); var p2 = new Person("Xie",65,"Boss"); alert(p1.frients); // Tom,Jerry alert(p2.frients); // Tom,Jerry p2.frients.push('Miki'); //Tom,Jerry,Miki
-
创建对象
理解原型对象
-
无论什么时候,只要创建了一个新函数,就会根据一套规则自动为该函数创建一个prototype属性
这个属性这项函数的原型对象,所有的原型对象都会自动获得一个contructor属性,这个属性包含一个
指向prototype属性所在函数的指针。这样就成了一个循环。如下图:
每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。首先从
对象实例本身开始,如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没找到,则继续搜索
指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到了这个属性,则返回该属性的值。
注意,可以通过对象实例访问保存在原型中的值,但不能通过对象实例重写原型中的值。因为,如果
在实例中添加了这个属性,而且这个属性和原型中的属性同名,那么就会屏保原型中的属性了,因为一下子就找到了。
sample:function Person(){} Person.prototype.name ='Tom'; Person.prototype.sayName = function(){ alert(this.name); } var p1 = new Person(); var p2 = new Person(); p1.name = 'Jerry'; alert(p1.name);//Jerry--来自实例 alert(p2.name);//Tom --来自原型
继承
- ECMAScript使用原型链来实现继承。利用原型链让一个引用类型继承另一个引用类型的属性和方法
最常用的是组合继承,也叫做伪经典继承。用原型链和构造函数集合在一起。
sample: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('Tom',12); instance1.colors.push('yellow'); alert(instance1.colors); instance1.sayName(); instance1.sayAge(); var instance2 = new SubType('Jerry',10); instance2.colors.push('white'); alert(instance1.colors); instance2.sayName(); instance2sayAge();