js面向对象

本文将循序渐进的介绍js面向对象的基础知识。


面向对象编程的好处

什么是面向对象呢?

一对象

面向对象编程 (OOP : Object Oriented Programming)。
它从90年代开始成为软件开发的主流思想。
它的概念就是将世间万物视为对象,并将其分类。
同一类的对象有相同的属性和行为。
比如,一个人,它包括性别、年龄,颜值等属性。还可以有些行为,比如:微笑、说话、吃饭、写代码等。

面向对象具有4个主要特性:

  • 唯一 :每个对象都有自身唯一的标识,通过这种标识,可找到相应的对象。在对象的整个生命期中,它的标识都不改变。
  • 抽象:将具有一致的属性和行为的对象抽象成类。反映了与应用有关的重要性质,而忽略其他一些无关内容。
  • 继承:继承子类自动共享父类数据结构和方法的机制,这是类之间的一种关系,继承性是面向对象思想最重要的一点。
  • 多态:多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。

面向对象与面向过程到底有什么区别?

  • 可维护性强
    写代码简单,维护起来却不容易。
    经过深思熟虑的抽象,松散的代码可以被重构为“有胳膊有腿”的个体,
    属于它的变量被定义成属性,相关的函数片段被定义成它的行为(方法),看到这样清晰的结构,对这些函数片段和散落的变量就会一目了然其作用。
  • 可复用性强
    说实话,在实际工作前,我读过面向对象的知识,但是从未应用过。
    直到工作中遇到一个特定的需求不得已为之,之后就爱上了这种写法。
    如果让你做一个轮播图,可能100行之内就可以搞定。但是,如果很多页面都需要你这个轮播图,但是有些许不同,比如轮播时间间隔,轮播方向,切换图片后的行为(轮播动画结束时需要执行的链接地址更新,统计等等等回调函数)。
    或者,一个页面有两处轮播,而且两处的class,行为不同,你会将那段代码改吧改吧复制成两个吗?
    如果是面向对象,就可以将方法,属性抽象,初始化不同的实例,实例间求同存异,各自都有自己的状态,互不影响。

如何用JS写面向对象?

创建对象的最简单方式就是创建一个Object实例,然后为它添加属性和方法。

  • 普通模式
var person = new Object();
person.name = ‘Taylor Swift’;
person.job = ‘singer’;
person.sayName =function(){
    alert(this.name);
}

这样,一个有名字,有工作,会说话的人就诞生了。但是如果批量生产多个对象实例呢?

  • 工厂模式:
var create = function(name, job){
    var o= new Object();
    o.name = name;
    o.job = job;
    o.sayName =function(){
        alert(this.name);
    }
    return o;
}
var person = create('Taylor Swift','singer');

这样,我们就可以将实例间的区别以参数的方式传递给工厂函数,返回给我们对象实例。但是,实例却不知道“爹”是谁?

  • 构造函数模式:
var Person = function(name, job){
    this.name = name;
    this.job = job;
    this.sayName =function(){
        alert(this.name);
    }
}
var person1 = new Person('Taylor Swift','singer');
console.log(person1 instanceof Person);

利用构造模式的instanceof方法我们就可以做“亲自鉴定”了。但是注意看,实例化几个对象,就会有多少sayName()方法,但是sayName()方法都相同,没必要浪费内存啊。这样写可不可以?

var Person = function(name, job){
    this.name = name;
    this.job = job;
    this.sayName = sayName;
}
function sayName(){
    alert(this.name);
}

把sayName单独提取出来就可以了,但是看着功能构造器Person没什么关系,很松散。
这时候就要引入一个js中原型对象的概念。

  • 原型对象:
    无论什么时候,只要创建了一个新函数,就会为该函数创建一个prototype属性,这个属性指向函数的原型对象。所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针。
    就拿前面的例子来说,Person.prototype.consructor 指向 Person.

用原型对象的方式写:

 var Person = function(){};
Person.prototype.name = 'Taylor Swift';
Person.prototype.job = 'singer';
Person.prototype.sayName = function(){
    alert(this.name);
};

我们看看原型方式的内存使用图:


内存使用图.png

但是原型模式还不够完美,它省略了为构造函数传递初始化参数的环节,结果所有实例在默认情况下都获得相同的属性值。
另外,因为的共享机制这个优点,存在一个潜在的问题。
如果共享的对象是引用类型(比如Array),实例之间可能会相互影响。比如下面的例子:

    var Person = function(){};
    Person.prototype.name = 'Taylor Swift';
    Person.prototype.job = 'singer';
    Person.prototype.friends = ['Ivy', 'Cathy'];
    Person.prototype.sayName = function(){
        alert(this.name);
    };
    var person1 = new Person();
    var person2 = new Person();
    person2.friends.push('jordan');
    console.log(person1.friends,person2.friends);

那么,接下来,我们最优的模式就要亮相了:

    var Person = function(){
        this.friends = ['Ivy', 'Cathy'];
        this.name = 'Taylor Swift';
        this.job = 'singer';
    };
    Person.prototype.sayName = function(){
        alert(this.name);
    };

ES6的写法会更简单:

class Person {
    constructor(name) {
        this.name = name;
        this.job = job;
    }
    sayName() {
        console.log(this.name);
    }
}

虽然目前es6兼容性还不够好,但是如果你想用这种写法的话,可以用编译工具,开发环境的文件是es6,生产环境运行的是编译后的es5写法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 大家好,我是IT修真院深圳分院第01期学员,一枚正直纯洁善良的web程序员。 今天给大家分享一下,修真院官网JS(...
    老菜菜阅读 1,298评论 0 2
  • title: js面向对象date: 2017年8月17日 18:58:05updated: 2017年8月27日...
    lu900618阅读 582评论 0 2
  • 1.JS对象创建的三种方式 1.第一种形式 工厂模型 function Person(){}// 添加原型属性Pe...
    呦释原点阅读 490评论 0 8
  • 原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好。 不...
    晨光2016阅读 1,310评论 8 13
  • 大家快来看我写的小说吧,下载[阅听 夏日炎炎的六月,叶冰还在为自己没有考进大学而失落。急促的脚步声向门靠近,脚...
    林聪哥阅读 268评论 0 0