JavaScript面向对象(收集整理)
(1)封装
首先理解构造函数:所谓"构造函数",其实就是一个普通函数,但是内部使用了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
构造函数存在一个弊端:浪费内存,比如:
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.eat == cat2.eat); //false
其中前两个属性name,color是实例独自拥有的,cat1和cat2的name,color是不同的,而type,eat()确是可以共同拥有的,所有可以把共有的方法,属性定义在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.eat == cat2.eat); //true
这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。
(2)继承
function Animal(){
this.species = "动物";
}
function Cat(name,color){
this.name = name;
this.color = color;
}
(Cat要继承Animal)
1.构造函数绑定
使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行
function Cat(name,color){
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
2. prototype模式
将Cat(子)的prototype指向Animal(父)的实例,那么Cat所创建出来的实例就都继承了Animal
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
其中第二行代码 Cat.prototype.constructor = Cat; 是因为如果原本constructor本来是指向自己的构造函数cat()的,但是这里被赋值给了new Animal(),换了个新构造函数,所以为了不造成继承链的紊乱,必须手动修改回来
3. 直接继承prototype
Cat不变的属性或方法可以直接写入Animal.prototype,然后Cat.prototype = Animal.prototype直接继承
function Animal(){ }
Animal.prototype.species = "动物";
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
这样的好处是,对比方法2中,不用执行和建立Animal()的实例,也省了内存;
这样的缺点是,由于Cat.prototype = Animal.prototype,Cat.prototype和Animal.prototype现在指向了同一个对象,实际上把Animal.prototype对象的constructor属性也改掉了!
4.利用空对象作为中介
用一个F空对象,几乎不占内存,作为中间桥梁,修改Cat的prototype对象,就不会影响到Animal的prototype对象。
var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
可以封装成一个函数:
function extend(Child,Parent){
var F = function (){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.construction = Child;
Child.uber = Parent.prototype; //假设一个Child不变的属性uber
}
extend(Cat,Animal);
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
5.拷贝继承
把父对象的所有属性和方法,拷贝进子对象
function Animal(){}
Animal.prototype.species = "动物";
function extend2(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
}
extend2(Cat, Animal);
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
(3)非构造函数继承
1.object()方法
var Chinese = {
nation:'中国'
};
var Doctor ={
career:'医生'
}
如何使Doctor对象继承Chinese对象?
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var Doctor = object(Chinese);
Doctor.career = '医生';
alert(Doctor.nation); //中国
2.浅拷贝:
只是拷贝基本类型的数据
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
return c;
}
var Doctor = extendCopy(Chinese);
Doctor.career = '医生';
alert(Doctor.nation); // 中国
Chinese.birthPlaces = ['北京','上海','香港']; var Doctor = extendCopy(Chinese);
Doctor.birthPlaces.push('厦门');
alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门
下面的代码显露出钱浅拷贝的缺点,就是假如父对象的某个属性也是数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。
3.深拷贝
jQuery库使用的就是这种继承方法。
function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
var Doctor = deepCopy(Chinese);
Chinese.birthPlaces = ['北京','上海','香港'];
Doctor.birthPlaces.push('厦门');
alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
alert(Chinese.birthPlaces); //北京, 上海, 香港
以上内容均参考自:
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html
JavaScript面向对象(收集整理)的更多相关文章
- javascript收集整理
//特殊字符去掉 function check(obj){ var test=obj.value.match(/[^A-Za-z0-9]/g);//这条语句表示在输入文本中是否包含不符合要求的字符,如 ...
- javascript面向对象精要第三章对象整理精要
什么是对象的数据属性?什么是对象的访问器属性?[put]方法是默认创建数据属性的,访 问器属性不包含值而是定义了一个单属性被读取时调用的函数(getter)和当一个属性被写入时 调用的函数(sette ...
- JavaScript 正则表达收集整理
JavaScript 正则表达收集整理 //可为空 /^\s*$/ //密码验证,必须且只含有数字和字母,可以拥有英文符号,6-17位 /(?=.{,})(?=.*\d)(?=.*[a-z])[\x2 ...
- javascript 面向对象整理
整理一下js面向对象中的封装和继承. 1.封装 js中封装有很多种实现方式,这里列出常用的几种. 1.1 原始模式生成对象 直接将我们的成员写入对象中,用函数返回. 缺点:很难看出是一个模式出来的实例 ...
- 【理论面试篇】收集整理来自网络上的一些常见的 经典前端、H5面试题 Web前端开发面试题
##2017.10.30收集 面试技巧 5.1 面试形式 1) 一般而言,小公司做笔试题:大公司面谈项目经验:做地图的一定考算法 2) 面试官喜欢什么样的人 ü 技术好. ...
- 【编码题篇】收集整理来自网络上的一些常见的 经典前端、H5面试题 Web前端开发面试题
编写一个方法 求一个字符串的字节长度假设:一个英文字符占用一个字节,一个中文字符占用两个字节 function GetBytes(str){ var len = str.length; var byt ...
- 最常用的PHP正则表达式收集整理
最常用的PHP正则表达式收集整理 提交 我的评论 加载中 已评论 最常用的PHP正则表达式收集整理 2015-03-20 PHP100中文网 PHP100中文网 PHP100中文网 微信号 功能介绍 ...
- 闭包初体验 -《JavaScript面向对象编程指南》
下面是我对闭包的理解:(把他们整理出来,整理的过程也是在梳理) 参考<JavaScript面向对象编程指南> 1.首先,在理解闭包之前: 我们首先应该清楚下作用域和作用域链 作用域:每个函 ...
- 工作流,WEB框架,UI组件网络收集整理
工作流,WEB框架,UI组件网络收集整理 在博客园上逛了好多年,随手收录了一些工作流,WEB开发框架,UI组件,现在整理一下与大家分享. 由于个人能力与精力有限,望各位园友在评论中补充,我将全部整理到 ...
- JavaScript面向对象—深入ES6的class
JavaScript面向对象-深入ES6的class 前言 在前面一篇中主要介绍了JavaScript中使用构造函数+原型链实现继承,从实现的步骤来说还是比较繁琐的.在ES6中推出的class的关键字 ...
随机推荐
- 约会安排HDU - 4553
寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复"呵呵",所以,小明的最爱就是和女神们约会.与此同时,也有很多基 ...
- 一个高性能、轻量级的分布式内存队列系统--beanstalk
Beanstalk是一个高性能.轻量级的.分布式的.内存型的消息队列系统.最初设计的目的是想通过后台异步执行耗时的任务来降低高容量Web应用系统的页面访问延迟.其实Beanstalkd是典型的类Mem ...
- C#仪器数据文件解析-RTF文件
RTF格式文件大家并不陌生,但RTF文件的编码.解码却很难,因为RTF文件是富文本格式的,即文件中除了包含文本内容,还包含文本的格式信息,而这些信息并没有像后来的docx等采用XML来隔离格式和内容, ...
- 【转】Python中实现远程调用(RPC、RMI)简单例子
远程调用使得调用远程服务器的对象.方法的方式就和调用本地对象.方法的方式差不多,因为我们通过网络编程把这些都隐藏起来了.远程调用是分布式系统的基础. 远程调用一般分为两种,远程过程调用(RPC)和远程 ...
- 【转】Python正则表达式指南
1. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十 ...
- webpack 的使用2
实际项目中的配置 要加__dirname 不然会报错 注意path /dist 前不要加点 结果 将两个文件打包在一起 结果 传入对象 并且单独打包 name为key 加上本次打包的hash has ...
- 浅析php curl_multi_*系列函数进行批量http请求
何起: 一系列 数量很大 数据不热 还希望被蜘蛛大量抓取的页面,在蜘蛛抓取高峰时,响应时间会被拉得很高. 前人做了这样一个事儿:页面分3块,用3个内部接口提供,入口文件用curl_multi_*系列函 ...
- 【MVC】会员注册/登录,普通验证,会员名是否注册Ajax验证以及会员邮件验证实现原理
using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentM ...
- IOS应用FFMPEG库
1.引用资源 build-ffmpeg ffmpeg库生成 -sh开源地址: https://gist.github.com/m1entus/6983547 iFrameExtractor ffmp ...
- Linux下搭建svn服务端
安装 使用yum安装非常简单: yum -y install subversion (压缩包安装比这麻烦的多) Tortoise本是window下客户端工具,但也可以建仓库,作为服务端.Linux只有 ...