学习http://www.cnblogs.com/elonhu/p/6984609.html
ES5
/*类的创建*/
function Dog() {
//构造函数:人们一致协定把构造函数的名字(即类名),首字母大写,以便区分
this.hairColor = '白色';
/*this指向被创造的对象(实例),如果不明白可以简单的理解为给对象(this)赋予hairColor这个属性
*/
this.breed = '贵宾';
this.age = 2;
this.runSpeed = null; //string
/*属性的声明一定要放在构造函数的最顶部;
有的属性可能一开始没有初始值,会在方法里才赋值,但你一定要在构造函数里声明一下
有必要的话再声明一下属性的类型
*/
}
Dog.prototype.shout = function() {
/*我们把方法追加到构造函数的prototype属性,而不是直接在构造函数里用this.shout = function(){};
这样的好处是会让Dog创造的所有对象都共享一个方法,从而节约内存;
一般来说属性在构造函数里赋予,方法在prototype里赋予;
*/
console.log('汪!汪!汪!我是一只' + this.age + '岁的' + this.hairColor + this.breed);
//方法里通过this可以访问属性
}
ES6
class Dog {
constructor(hairColor, breed, age) { //代表这个类的构造函数
this.hairColor = hairColor; //string
this.breed = breed; //string
this.age = age; //number
this.runSpeed = null; //string
Dog.instanceNumber++;
}
shout() {
console.log('汪!汪!汪!我是一只' + this.age + '岁的' + this.hairColor + this.breed);
}
run() {
this.runSpeed = '10m/s';
console.log('吃我灰吧,哈哈!本狗的速度可是有' + this.runSpeed);
}
gnawBone() {
console.log('这是本狗最幸福的时候');
}
getInstanceNumber() {
return Dog.instanceNumber;
}
}//ES6类的创建就比较舒服了,class把整个类用{}包裹在一起,写法也比较方便。
Dog.instanceNumber = 0;//遗憾的是ES6里也没有规范静态属性,还是跟ES5一样的用法,据说ES7已有一个静态属性的提案
let dog1 = new Dog('白色', '贵宾', 2);
let dog2 = new Dog('棕色', '泰迪', 1);
let dog3 = new Dog('黑色', '土狗', 3);
dog1.shout(); //log: '汪!汪!汪!我是一只2岁的白色贵宾'
dog2.shout(); //log: '汪!汪!汪!我是一只1岁的棕色泰迪'
dog3.shout(); //log: '汪!汪!汪!我是一只3岁的黑色土狗'
console.log(dog1.getInstanceNumber()); //log: 3;
类的抽象
上面的例子是我们明确知道要创建一个对象(实例)dog,但实际开发当中是没有人告诉我们需要创建哪些对象的,领导给我们的只有需求,所以我们要分析需求的业务逻辑,把需求分解成一个个对象。
比如说现在领导给我们一个需求:做一个超市收银系统,分为两种角色:收银员和管理员,收银员可以查询物品信息、统计价格、录入账单信息、打印小票,管理员可以查看账单信息、统计账单信息。
注意需求中的名词:收银员、管理员、物品信息、账单、小票,这些就是天然的对象,这是最初步的抽象。
让我们再注意动词:查询、统计、录入、打印,我们是不是也可以抽象成对象?查询器?统计器?
然后我们开始coding吧,不要纠结自己的抽象是否完美,作者很赞同Facebook的一句标语:Done is better than perfect(比完美更重要的是完成).
当某个对象的代码不断膨胀,慢慢超出控制的时候(作者自己的的标准是一个对象尽量不超过300行代码),这时候你就得考虑更深层次的抽象了,查找这个对象里代码比较多的属性、方法、然后抽象成另一个对象,把新对象作为原先对象的成员(属性)。
function Dog(){
this._tail = new Tail();//把尾巴tail抽象成另一个对象,作为dog的一个属性;
}