珠峰培训javascript技术与前端技术论坛

 找回密码
 立即注册
查看: 1534|回复: 2

javascript面向对象实现

[复制链接]

23

主题

44

帖子

151

积分

注册会员

Rank: 2

积分
151
发表于 2015-4-1 23:05:38 | 显示全部楼层 |阅读模式
本帖最后由 mxtkwy 于 2015-4-1 23:15 编辑

今天在研究组件面向对象的写法,看到这篇文章情不自禁的来跟大家一起分享,相信看完后会受益很多!重点是了解到我们不能只停留与表面,要多多探索研究!

原始时代最简单的oo实现javascript虽然没有class的概念,但是它的函数却是可以new出来一个对象的。所以一个最简单的class就可以用function来模拟出来。
  1. function Animal(name){
  2.     this.name = name;
  3.     this.run = function(){
  4.         console.log(this.name + "is running!!");
  5.     }
  6. }

  7. var pet = new Animal("pet");
  8. pet.run();//petis running!!
复制代码
这样 pet就有了属性,有了方法,不过这种写法毫无继承性,扩展性。比如我们要实现个dog类,只能把属性方法再写一遍。而且每个new出来的对象都有自己的方法,造成资源浪费。
在javascript里面有个原型链的概念,每一个函数都有一个prototype对象属性。这样通过这个函数new出来的对象会自动具有__proto__属性指向函数的prototype对象。说白了所有的实例对象都会共用一个prototype对象,并且调用一个属性或者方法时在自己上面找不到,就会找__proto__对象有没有,之后一直往上追溯一直到找到为止。具体表现为:
  1. function Animal(name){
  2.     this.name = name;
  3. }
  4. Animal.prototype.run = function(){
  5.     console.log(this.name + "is running!!");
  6. }
  7. var a = new Animal("a");
  8. var b = new Animal("b");
  9. console.log(Animal.prototype) //Animal {}
  10. console.log(Animal.prototype instanceof Object) //true prototype是个对象
  11. console.log(Animal.prototype.constructor == Animal)//true
  12. console.log(a.__proto__ == Animal.prototype) //true __proto__在new的时候会自动加载在实例对象上。在现代浏览器里可以看到
  13. console.log(b.__proto__ == Animal.prototype) //true
  14. console.log(a.__proto__.__proto__) //Object {} 最后会找到最上面的boject对象
  15. console.log(a.__proto__.run == a.run) //true
  16. console.log(a.__proto__.run == a.prototype.run) //true
复制代码

所以,在prototype对象上定义的方法会被所有实例共享,这不就是复用吗?
于是有了基于原型链的继承的写法:
  1. function Animal(name){
  2.     this.name = name;
  3. }
  4. Animal.prototype.run = function(){
  5.     console.log(this.name + "is running!!");
  6. }
  7. function Dog(name){
  8.     //调用父类的构造函数,通过改变this指向将属性赋值到新的实例对象
  9.     Animal.call(this,name);
  10. }
  11. Dog.prototype = new Animal();
  12. var dog = new Dog("dog");
  13. dog.run();//dog is running!!
复制代码

可以看到我们将Animal的实例对象暂且叫做a,作为 Dog的prototype,这样 Dog的实例对象dog的__proto__指向Dog的prototype也就是a,a的__proto__再指向Animal的prototype对象,这个对象上有run方法。于是我们调用dog.run()的时候会一层层的往上追溯一直找到run方法执行。于是通过原型链我们就让 Dog继承了Animal的方法run。
需要注意的是,如果在子类的prototype对象上也有run方法,就会覆盖父类的,因为查找时在自己上面就找到了,就不会向上回溯了。
上面是原型链方法的继承。而属性我们则是通过调用父类的构造函数来赋值的。因为属性不能所有的实例都公用,应该每个人都有自己的一份,所以不能放在原型上。
上面就是原始时代最简单的类继承了。


回复

使用道具 举报

23

主题

44

帖子

151

积分

注册会员

Rank: 2

积分
151
 楼主| 发表于 2015-4-1 23:11:47 | 显示全部楼层
石器时代的oo实现
这个时代javascript变得比较重要了,作为非常有用的特性,oo开始被很多人研究。

首先上面的那种简单oo实现方式,其实是有很多问题的。
1.没有实现传统oo该有的super方法来调用父类方法。
作为oo,怎么能没有super呢。作为我们前端界宗师一般的人物。Douglas 有一篇经典文章。不过貌似有很多问题。国内的玉伯分析过。在这里

最后Douglas总结出来:

我编写 JavaScript 已经 8 个年头了,从来没有一次觉得需要使用 uber 方法。在类模式中,super 的概念相当重要;但是在原型和函数式模式中,super 的概念看起来是不必要的。现在回顾起来,我早期在 JavaScript 中支持类模型的尝试是一个错误。

2.直接将父类实例作为子类的原型,简单粗暴造成多余的原型属性。还有construct的问题。
这个问题主要是之前代码里面这一句造成的:

  1. Dog.prototype = new Animal();
  2. //var dog = new Dog("dog");
  3. //console.log(dog.__proto__)     Animal {name: undefined}
复制代码

执行new Animal()就会执行animal的构造函数,就会在Dog.prototype生成多余的属性值,这边是name。而一般属性值为了复用是不能放在原型对象上的。并且由于dog有自己的name属性,原型上的是多余的。

还有construct的问题。

  1. console.log(dog.constructor == Animal) //true
  2. console.log(dog.constructor == Dog) //false
复制代码


显然这不是我们希望看到的。

所以我们要对上面做些改良:
  1. var F = function(){};
  2. F.prototype = Animal.prototype;
  3. Dog.prototype = new F();
  4. Dog.prototype.constructor = Dog;
复制代码

我们可以封装下:

function objCreate(prototype){
    var F = function(){};
    F.prototype = prototype;
    return new F();
}
function inherit(subclass,parentclass){
    subclass.prototype = objCreate(parentclass.prototype);
    subclass.prototype.constructor = subclass;
}

于是继承可以写成:

function Animal(name){
    this.name = name;
}
Animal.prototype.run = function(){
    console.log(this.name + "is running!!");
}
function Dog(name){
    //调用父类的构造函数,通过改变this指向将属性赋值到新的实例对象
    Animal.call(this,name);
}
inherit(Dog,Animal);
var dog = new Dog("dog");
dog.run();//dog is running!!
回复 支持 反对

使用道具 举报

23

主题

44

帖子

151

积分

注册会员

Rank: 2

积分
151
 楼主| 发表于 2015-4-1 23:12:34 | 显示全部楼层
本帖最后由 mxtkwy 于 2015-4-1 23:17 编辑

工业时代的oo实现

.....后续......
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|珠峰培训--JavaScript培训

GMT+8, 2017-9-21 19:59 , Processed in 0.134843 second(s), 20 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表