美文网首页程序员
js之面对对象编程

js之面对对象编程

作者: 路耀广的前端微博 | 来源:发表于2018-02-26 14:56 被阅读0次

JavaScript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类)。

面向对象的语言有一个标志,即拥有类的概念,抽象实例对象的公共属性与方法,基于类可以创建任意多个实例对象,一般具有封装、继承、多态的特性!但JS中对象与纯面向对象语言中的对象是不同的,ECMA标准定义JS中对象:无序属性的集合,其属性可以包含基本值、对象或者函数。可以简单理解为JS的对象是一组无序的值,其中的属性或方法都有一个名字,根据这个名字可以访问相映射的值(值可以是基本值/对象/方法)。

JS对象的封装

最原始的对象封装:

这样的写法有两个缺点,一是如果多生成几个实例,写起来就非常麻烦;二是实例与原型之间,没有任何办法,可以看出有什么联系。

改进版:

这种方法生成出来的实例之间也没有一点联系,不能看出实例是同一个原型的。

构造函数:

所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。

这时我们想知道两个实例之间的关系,可以通过constructor属性来访问它们的构造函数。

Javascript还提供了一个instanceof运算符,验证原型对象与实例对象之间的关系。

这里我们还发现一个问题,就是构造函数会造成内存资源的浪费。即如果生成的实例中有很多一致的属性或方法。生成的每个实例都会去创建。这时我们可以通过构造函数的prototype属性去访问构造函数的原型对象去设置公共的属性或方法。在原型对象中的属性或方法在会默认被生成的实例继承。

为了配合prototype属性,Javascript定义了一些辅助方法,帮助我们使用它。

isPrototypeOf() 

这个方法用来判断,某个proptotype对象和某个实例之间的关系。

hasOwnProperty()

每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。

in运算符

in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。

JS构造函数的继承

js对象的继承的实现方法大致有5种方式。

一、 构造函数绑定

第一种方法也是最简单的方法,使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行:

二、 prototype模式

第二种方法更常见,使用prototype属性。

如果Dog的prototype对象,指向一个Animal的实例,那么所有Dog的实例,就能继承Animal了。

它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。

由于任何一个prototype对象都有一个constructor属性,指向它的构造函数。如果没有“Dog.prototype = new Animal();"这一行,Dog.prototype.constructor是指向Animal的;加了这一行以后,Dog.prototype.constructor指向Dog。

更重要的是,每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。如果不手动修改Dog.prototype的constructor属性。则该构造函数生成的实例的constructor属性都会指向Animal。造成继承链的混乱。

三、 直接继承prototype

第三种方法是对第二种方法的改进。由于Animal对象中,不变的属性都可以直接写入Animal.prototype。所以,我们也可以让Dog()跳过 Animal(),直接继承Animal.prototype。

与前一种方法相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。但是这种方法的缺点也是显而易见的。我们让Dog.prototype指向了Animal.prototype。这种引用类型的数据之间地址共享,使得只要修改了其中一个的值,另一个就会收到影响。

四、 利用空对象作为中介

这种方法是对上一种方法的修复,即利用一层空对象来解决。

F是空对象,所以几乎不占内存。这时,Dog与Animal之间相互修改彼此的prototype对象就不会彼此影响了。

五、 拷贝继承

上面是采用prototype对象,实现继承。我们也可以换一种思路,纯粹采用"拷贝"方法实现继承。简单说,如果把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?这样我们就有了第五种方法。

JS非构造函数的继承

什么是"非构造函数"的继承?

object方法 

利用构造函数的prototype指向Chinese对象,并返回实例。

浅拷贝

除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。

但是,这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。

深拷贝

所谓"深拷贝",就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。

相关文章

  • js之面向对象编程

    (1)构造器和类 当使用new运算符调用一个函数的时候,它总是返回一个对象,在函数体内部,这个对象称为this,即...

  • js之面对对象编程

    JavaScript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。但是,它又不是...

  • JS进阶系列之面向对象编程

    ECMAScript中没有类的概念,里面对于对象的描述是:“无序属性的集合、其属性可以包含基本值、对象或者函数” ...

  • JS之面向对象

    一、理解对象 创建自定义对象的最简单方式就是创建一个 Object 的实例,然后为它添加属性和方法。 对象字面量成...

  • JS之面向对象

    JavaScript是基于原型(prototype), 没有python中class 的概念。 构造函数在Java...

  • JS之面向对象

    在JS中几乎一切皆对象。JS中将对象定义为:一组无序键值对的集合,属性以及方法的名称就是键,键的值可以是任何类型(...

  • JS之面向对象

    什么是面向对象? 面向对象是一种编程思想,是在面向过程编程(结构化编程)之后出现的,面向对象的思想基于抽象数据类型...

  • 7.1.1 PHP面向对象之面向过程详解

    7.1.1 PHP面向对象之面向过程详解面向对象的编程思想Object Oriented 大象与冰箱1、打开2、装...

  • python之面向对象编程

    面向对象和面向过程的基本概念 面向过程:侧重于怎么做。1、把完成一个需求的所有步骤 从头到尾 逐步实现2、根据开...

  • Python之面向对象编程

    面向对象编程中最重要的一个概念也就是类和对象。所以下面来介绍一下类的相关内容 类和对象 类是抽象的模板,比如我们抽...

网友评论

    本文标题:js之面对对象编程

    本文链接:https://www.haomeiwen.com/subject/brryxftx.html