属性类型
- 数据属性
var person = {}; Object.defineProperty(person, 'name', { value: 'Chengjie ZHANG', writable: false, //是否可修改(只读) enumerable: false, //是否可枚举,false则不能被for-in检测到 configurable: false //一旦是false,那就不能再被还原成true了 });
Object.defineProperty()可以对一个property使用多次 - 访问器属性
var person = {}; Object.defineProperty(person, 'name', { get: function(){ return this.name; }, set: function(val){ this.name = val; } });
Vue 2.0的双向数据绑定就是这样实现的。详见Vue笔记
原型模式
//由于ES中函数也是对象,所以成员函数写在构造函数里面的话,每个实例对象的成员函数都被重复实例化了。 person1.say() == person2.say() //false
__proto__(隐式原型)与prototype(显式原型)
两者关系:实例对象的是隐式的,函数对象是显示的。
prototype显式原型的作用:用来实现基于原型的继承与属性的共享。
__proto__隐式原型的作用:构成原型链,同样用于实现基于原型的继承。大多数浏览器都支持通过__proto__来访问。ES5新增Object.getPrototypeOf(obj).
1. prototype(显式原型)
Person.prototype最初只有包含constructor一个属性
in操作符只要对象能够访问到就返回true
hasOwnProperty()存在与对象实例本身,而不存在于原型上
hasPrototypeProperty()存在于对象的原型上。
原型屏蔽问题
var person = new Person(); alert( "name" in person ); //true alert( Object.prototype.hasOwnProperty(p, 'name') ); //false
2. __proto__(隐式原型)
在调用person1.sayName()的时候:
- person1下面有没有sayName? 没有
- person1.__proto__指向Person Prototype下有没有sayName?有的,返回sayName
- sayName()执行
存在一个原型动态性的问题
function Person(){ } var friend = new Person(); Person.prototype = { constructor: Person, name: 'myName', sayName: function (){ console.log(this.name); } }; Person.prototype.sayHi = function(){ alert("hi"); }; friend.sayHi(); //"hi"(没有问题!) friend.sayName(); //error
继承
*核心:SubType.prototype = new SuperType(); *
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了 SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function (){ return this.subproperty; }; var instance = new SubType(); alert(instance.getSuperValue()); //true
组合继承模式(原型链+借用构造函数)
使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
也叫做伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。
这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。如果是想要用静态属性的话,就把属性挂在原型链上
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); //继承属性,确保colors独立 this.age = age; } SubType.prototype = new SuperType(); //继承方法 SubType.prototype.constructor = SubType; //实例对象指回自己,因为有age属性,朴素原型继承法里,prototype是没有constructor的 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