学习Javascript面向对象编程之封装


Posted in Javascript onFebruary 23, 2016

Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类)。
那么,如果我们要把"属性"(property)和"方法"(method),封装成一个对象,甚至要从原型对象生成一个实例对象,我们应该怎么做呢?
一、 生成对象的原始模式
假定我们把猫看成一个对象,它有"名字"和"颜色"两个属性。

var Cat = {

name : '',


color : ''

}

现在,我们需要根据这个原型对象的规格(schema),生成两个实例对象。 

var cat1 = {}; // 创建一个空对象

cat1.name = "大毛"; // 按照原型对象的属性赋值


cat1.color = "黄色";

var cat2 = {};


cat2.name = "二毛";


cat2.color = "黑色";

好了,这就是最简单的封装了,把两个属性封装在一个对象里面。但是,这样的写法有两个缺点,一是如果多生成几个实例,写起来就非常麻烦;二是实例与原型之间,没有任何办法,可以看出有什么联系。
二、 原始模式的改进
我们可以写一个函数,解决代码重复的问题。

function Cat(name,color){

return {



name:name,



color:color


}

}

然后生成实例对象,就等于是在调用函数:

var cat1 = Cat("大毛","黄色");
var cat2 = Cat("二毛","黑色");

这种方法的问题依然是,cat1和cat2之间没有内在的联系,不能反映出它们是同一个原型对象的实例。
三、 构造函数模式
为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。
所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
比如,猫的原型对象现在可以这样写,
 

 function Cat(name,color){

this.name=name;


this.color=color;

}

我们现在就可以生成实例对象了。

 var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");

alert(cat1.name); // 大毛

alert(cat1.color); // 黄色

这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。 

alert(cat1.constructor == Cat); //true
alert(cat2.constructor == Cat); //true

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

 alert(cat1 instanceof Cat); //true
alert(cat2 instanceof Cat); //true

四、构造函数模式的问题
构造函数方法很好用,但是存在一个浪费内存的问题。
请看,我们现在为Cat对象添加一个不变的属性"type"(种类),再添加一个方法eat(吃老鼠)。那么,原型对象Cat就变成了下面这样: 

 function Cat(name,color){

this.name = name;


this.color = color;


this.type = "猫科动物";


this.eat = function(){alert("吃老鼠");};

}

还是采用同样的方法,生成实例:

 var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat ("二毛","黑色");

alert(cat1.type); // 猫科动物

cat1.eat(); // 吃老鼠

表面上好像没什么问题,但是实际上这样做,有一个很大的弊端。那就是对于每一个实例对象,type属性和eat()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容,多占用一些内存。这样既不环保,也缺乏效率。

alert(cat1.eat == cat2.eat); //false

能不能让type属性和eat()方法在内存中只生成一次,然后所有实例都指向那个内存地址呢?回答是可以的。
五、 Prototype模式
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上:

 function Cat(name,color){

this.name = name;


this.color = color;

}

Cat.prototype.type = "猫科动物";

Cat.prototype.eat = function(){alert("吃老鼠")};

然后,生成实例。

 var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");

alert(cat1.type); // 猫科动物

cat1.eat(); // 吃老鼠

这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。

 alert(cat1.eat == cat2.eat); //true

六、 Prototype模式的验证方法
为了配合prototype属性,Javascript定义了一些辅助方法,帮助我们使用它。,
6.1 isPrototypeOf()
这个方法用来判断,某个proptotype对象和某个实例之间的关系。

 alert(Cat.prototype.isPrototypeOf(cat1)); //true
alert(Cat.prototype.isPrototypeOf(cat2)); //true

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

 alert(cat1.hasOwnProperty("name")); // true
alert(cat1.hasOwnProperty("type")); // false

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

 alert("name" in cat1); // true
alert("type" in cat1); // true

in运算符还可以用来遍历某个对象的所有属性。 

 for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); }

以上就是关于javascript封装的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
浅析document.ready和window.onload的区别讲解
Dec 18 Javascript
Javasipt:操作radio标签详解
Dec 30 Javascript
JS实现带关闭功能的阿里妈妈网站顶部滑出banner工具条代码
Sep 17 Javascript
jQuery事件绑定用法详解
Sep 08 Javascript
Bootstrap基本插件学习笔记之轮播幻灯片(23)
Dec 08 Javascript
vue v-on监听事件详解
May 17 Javascript
使用vue制作FullPage页面滚动效果
Aug 21 Javascript
babel的使用及安装配置教程
Feb 22 Javascript
JS中DOM元素的attribute与property属性示例详解
Sep 04 Javascript
vue Tab切换以及缓存页面处理的几种方式
Nov 05 Javascript
微信小程序点击view动态添加样式过程解析
Jan 21 Javascript
前端性能优化建议
Sep 17 Javascript
javascript每日必学之封装
Feb 23 #Javascript
jQuery常用知识点总结以及平时封装常用函数
Feb 23 #Javascript
使用Javascript实现选择下拉菜单互移并排序
Feb 23 #Javascript
jQuery拖拽排序插件制作拖拽排序效果(附源码下载)
Feb 23 #Javascript
JavaScript tab选项卡插件实例代码
Feb 23 #Javascript
Javascript技术栈中的四种依赖注入详解
Feb 23 #Javascript
JQuery+EasyUI轻松实现步骤条效果
Feb 22 #Javascript
You might like
PHP中“简单工厂模式”实例代码讲解
2012/09/04 PHP
sql注入与转义的php函数代码
2013/06/17 PHP
php页码形式分页函数支持静态化地址及ajax分页
2014/03/28 PHP
PHP工程师VIM配置分享
2015/12/15 PHP
支付宝支付开发――当面付条码支付和扫码支付实例
2016/11/04 PHP
Laravel 登录后清空COOKIE的操作方法
2019/10/14 PHP
Laravel 解决composer相关操作提示php相关异常的问题
2019/10/23 PHP
文字幻灯片
2006/06/26 Javascript
jQuery powerFloat万能浮动层下拉层插件使用介绍
2010/12/27 Javascript
jquery三个关闭弹出层的小示例
2013/11/05 Javascript
ext中store.load跟store.reload的区别示例介绍
2014/06/17 Javascript
jQuery插件uploadify实现ajax效果的图片上传
2016/06/18 Javascript
Javascript实现图片加载从模糊到清晰显示的方法
2016/06/21 Javascript
jQuery动态修改字体大小的方法【测试可用】
2016/09/09 Javascript
微信小程序 石头剪刀布实例代码
2017/01/04 Javascript
JavaScript拖动层Div代码
2017/03/01 Javascript
Vue2.0使用过程常见的一些问题总结学习
2017/04/10 Javascript
傻瓜式vuex语法糖kiss-vuex整理
2018/12/21 Javascript
Layui数据表格判断编辑输入的值,是否为我需要的类型详解
2019/10/26 Javascript
微信小程序中限制激励式视频广告位显示次数(实现思路)
2019/12/06 Javascript
Python模块学习 re 正则表达式
2011/05/19 Python
python函数缺省值与引用学习笔记分享
2013/02/10 Python
Python3视频转字符动画的实例代码
2019/08/29 Python
Python求两个字符串最长公共子序列代码实例
2020/03/05 Python
利用python+ffmpeg合并B站视频及格式转换的实例代码
2020/11/24 Python
CSS3 display知识详解
2015/11/25 HTML / CSS
SheIn俄罗斯:时尚女装网上商店
2017/02/28 全球购物
Clarisonic美国官网:科莱丽声波洁面仪
2017/10/12 全球购物
美国巧克力喷泉品牌:Sephra
2019/05/05 全球购物
Zooplus罗马尼亚:宠物食品和配件
2019/11/02 全球购物
Madda Fella官网:美国冒险家服装品牌
2020/01/16 全球购物
在网络中有两台主机A和B,并通过路由器和其他交换设备连接起来,已经确认物理连接正确无误,怎么来测试这两台机器是否连通?如果不通,怎么来判断故障点?怎么排
2014/01/13 面试题
元旦联欢会策划方案
2014/06/11 职场文书
建筑节能汇报材料
2014/08/22 职场文书
小学生国庆节演讲稿
2014/09/05 职场文书
详解CocosCreator消息分发机制
2021/04/16 Javascript