属性类型

  1. 数据属性
    var person = {};
    Object.defineProperty(person, 'name', {
     value: 'Chengjie ZHANG',
     writable: false, //是否可修改(只读)
     enumerable: false, //是否可枚举,false则不能被for-in检测到
     configurable: false //一旦是false,那就不能再被还原成true了
    });
    Object.defineProperty()可以对一个property使用多次
  2. 访问器属性
    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).

prototype
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

隐式原型动态性问题

继承

heritage

*核心: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