web前端学习(二) javascript对象和原型继承
(1)javascript对象
var someone = {
name:'Tom',
age :,
work:'student',
showInfo:function(){
var str = "";
for(var name in this){
if(typeof(this[name]) != "function"){
str += this[name] + ' ';
}
}
console.log(str);
}
};
someone.showInfo(); //Tom 18 student
someone.hobby = 'music';
someone.showInfo(); //Tom 18 student music
从上面可以看出,直接量创建可以通过初始化时将已有对象赋值给它,也可以通过设置给对象添加新的属性,最后通过for/in循环就可以遍历出对象的所有属性,
构造函数方式:
//构造函数创建对象
function CreatPeople(name, age, work) //构造函数
{
this.name = name;
this.age = age;
this.work = work; this.showInfo = function(){
var str = "";
for(var name in this){
if(typeof(this[name]) != "function"){
str += this[name] + ' ';
}
}
console.log(str);
}
} var someone = new CreatPeople("Tom", , "student"); //实例对象
someone.showInfo(); //Tom 18 student var otherone = new CreatPeople("BoB", , "engineer");
otherone.showInfo(); //Bob 25 enginee
对比直接量方式和构造函数方式创建的对象,它们具有相同的属性name, age, work以及方法showInfo,功能相同。其中构造函数方式可以通过函数实现多个不同对象的创建,不过当我们希望给CreatPeole创建的对象添加新的属性habby时,单独每个对象都添加就过于繁琐,为了方便上述过程,js引入不同于C++类方式的继承模式,具体详见下章:原型对象和继承。
(2)原型对象和继承
function CreatPeople(name, age, work){
this.name = name;
this.age = age;
this.work = work;
}
CreatPeople.prototype.showInfo = function(){
var str = "";
for(var name in this){
if(typeof(this[name]) != "function"){
str += this[name] + ' ';
}
}
console.log(str);
}
function ExtraCreatPeople(name, age, work, hobby){
CreatPeople.apply(this, arguments);
this.hobby = hobby;
}
ExtraCreatPeople.prototype = new CreatPeople();
ExtraCreatPeople.prototype.data = ;
ExtraCreatPeople.prototype.constructor = ExtraCreatPeople;
var someone = new CreatPeople("Tom", , "student");
someone.showInfo(); //Tom 18 student
var otherone = new ExtraCreatPeople("Bob", , "student", "Sing");
otherone.showInfo(); //Bob 18 student sing 1
通过子类原型继承,生成了一个新的构造函数,实现了对于原构造函数的扩展。不过如果仔细看上面的代码,我们就会发现ExtraCreatePeople创建的对象时会调用两次new,这就造成了内存的浪费,同时也影响了效率。上面我们提到过,每一个函数都有一个原型对象,通过原型链由构造函数创建的对象具有原型对象的属性和方法,那么我们将CreatePerson的的原型对象直接借用给ExtraCreatePerson,是不是也可以实现目的呢?
function CreatPeople(name, age, work){
this.name = name;
this.age = age;
this.work = work;
}
CreatPeople.prototype.showInfo = function(){
var str = "";
for(var name in this){
if(typeof(this[name]) != "function"){
str += this[name] + ' ';
}
}
console.log(str);
}
function ExtraCreatPeople(name, age, work, hobby){
CreatPeople.apply(this, arguments);
this.hobby = hobby;
}
ExtraCreatPeople.prototype = CreatPeople.prototype;
ExtraCreatPeople.prototype.data = ;
ExtraCreatPeople.prototype.constructor = ExtraCreatPeople;
var someone = new CreatPeople("Tom", , "student");
someone.showInfo(); //Tom 18 student 1
var otherone = new ExtraCreatPeople("Bob", , "student", "Sing");
otherone.showInfo(); //Bob 18 student sing 1
通过借用原型链,也实现了相同的功能,不过仔细观察,就会发现借用原型引入了新的问题,新构造函数会污染原有构造函数的原型链,从而给原构造函数添加了新的属性,这与我们上面提到的在不影响原有对象的基础上创建新构造函数的目的是不符合,在通过对比上面的new引用,我们发现new方式实现的新构造函数并不会污染原有原型链,结合以上两种模式,就实现下面的构造函数创建:
function CreatPeople(name, age, work){
this.name = name;
this.age = age;
this.work = work;
}
CreatPeople.prototype.showInfo = function(){
var str = "";
for(var name in this){
if(typeof(this[name]) != "function"){
str += this[name] + ' ';
}
}
console.log(str);
}
function F(){
}
F.prototype = CreatPeople.prototype;
function ExtraCreatPeople(name, age, work, hobby){
CreatPeople.apply(this, arguments);
this.hobby = hobby;
}
ExtraCreatPeople.prototype = new F();
ExtraCreatPeople.prototype.data = ;
ExtraCreatPeople.prototype.constructor = ExtraCreatPeople;
var someone = new CreatPeople("Tom", , "student");
someone.showInfo(); //Tom 18 student
var otherone = new ExtraCreatPeople("Bob", , "student", "Sing");
otherone.showInfo(); //Bob 18 student sing 1
通过中间对象,实现了新构造函数与原构造函数的隔离,不过我们看下面的代码:
function CreatPeople(name, age, work){
this.name = name;
this.age = age;
this.work = work;
}
CreatPeople.prototype.showInfo = function(){
var str = "";
for(var name in this){
if(typeof(this[name]) != "function"){
if(typeof(this[name]) == "object"){
str += this[name].name + ' ';
}else{
str += this[name] + ' ';
}
}
}
console.log(str);
}
CreatPeople.prototype.child = {
name : "Lucy"
}
function F(){
}
F.prototype = CreatPeople.prototype;
function ExtraCreatPeople(name, age, work, habit){
CreatPeople.apply(this, arguments);
this.habit = habit;
}
ExtraCreatPeople.prototype = new F();
ExtraCreatPeople.prototype.data = ;
ExtraCreatPeople.prototype.constructor = ExtraCreatPeople;
var someone = new CreatPeople("Tom", , "student");
someone.showInfo(); //Tom 18 student Lucy
var otherone = new ExtraCreatPeople("Bob", , "student", "Sing");
otherone.showInfo(); //Bob 18 student sing 1 Lucy
someone.child.name = "pop";
someone.showInfo(); //Tom 18 student pop
otherone.showInfo(); //Bob 18 student sing 1 pop
在这里,很容易发现someone中对原型链上数据的修改导致otherone中的对应属性也发生了改变,这种错误隐蔽性高,不易发现,因此需要着重理解和掌握!不过通过上述了解,我们发现原型链的借用就是可以理解为对象的复制过程,就原构造函数对象的参数赋值给新的构造函数,同时两个构造函数对象不会互相影响,这里就要理解JS中对象中比较复杂的部分、浅拷贝和深拷贝,具体详见下段:对象的克隆。
3.对象的克隆
对象的克隆分为两种方式,浅度克隆:原始类型为值传递,对象类型仍为引用传递。深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。从这两部分可以看出来,上面的原型引用就是浅度克隆,为了对原型继承的要求,深度克隆就满足我们的要求,如下:
function isClass(obj){
if(obj == null) return "NULL";
if(obj == undefined) return "Undefiend";
return Object.prototype.toString.call(obj).slice(, -);
}
function deepclone(obj){
var result;
var objClass = isClass(obj);
//确定result的类型
if(objClass==="Object"){
result={};
}else if(objClass==="Array"){
result=[];
}else{
return obj;
}
for(key in obj){
var copy=obj[key];
if(isClass(copy)=="Object"){
result[key]=arguments.callee(copy); //递归调用
}else if(isClass(copy)=="Array"){
result[key]=arguments.callee(copy);
}else{
result[key]=obj[key];
}
}
return result;
}
function CreatPeople(name, age, work){
this.name = name;
this.age = age;
this.work = work;
}
CreatPeople.prototype.showInfo = function(){
var str = "";
for(var name in this){
if(typeof(this[name]) != "function"){
if(typeof(this[name]) == "object"){
str += this[name].name + ' ';
}else{
str += this[name] + ' ';
}
}
}
console.log(str);
}
CreatPeople.prototype.child = {
name : "Lucy"
}
function ExtraCreatPeople(name, age, work, habit){
CreatPeople.apply(this, arguments);
this.habit = habit;
}
ExtraCreatPeople.prototype = deepclone(CreatPeople.prototype);
ExtraCreatPeople.prototype.data = ;
ExtraCreatPeople.prototype.constructor = ExtraCreatPeople;
var someone = new CreatPeople("Tom", , "student");
someone.showInfo(); //Tom 18 student Lucy
var otherone = new ExtraCreatPeople("Bob", , "student", "Sing");
otherone.showInfo(); //Bob 18 student sing Lucy 1
someone.child.name = "pop";
someone.showInfo(); //Tom 18 student pop
otherone.showInfo(); //Bob 18 student sing Lucy 1
到此为止,子类和父类实现了完全的隔离,这也是实现原型继承最佳的方式。
web前端学习(二) javascript对象和原型继承的更多相关文章
- web前端学习:JavaScript学习指南
JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果.通常JavaScript脚本是通过嵌入在HTML中来实现 ...
- web前端学习python之第一章_基础语法(二)
web前端学习python之第一章_基础语法(二) 前言:最近新做了一个管理系统,前端已经基本完成, 但是后端人手不足没人给我写接口,自力更生丰衣足食, 所以决定自学python自己给自己写接口哈哈哈 ...
- web前端学习就这9个阶段,你属于哪个阶段?
第一阶段:HTML+CSS: HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础:Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMAsc ...
- 腾讯Web前端开发框架JX(Javascript eXtension tools)
转自:Web前端开发-Web前端工程师 » 腾讯Web前端开发框架JX(Javascript eXtension tools) JX – Javascript eXtension tools 一个类似 ...
- Web前端学习攻略
HTML+CSS: HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础: Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMAscript ...
- 进击的Python【第十四章】:Web前端基础之Javascript
进击的Python[第十四章]:Web前端基础之Javascript 一.javascript是什么 JavaScript 是一种轻量级的编程语言. JavaScript 是可插入 HTML 页面的编 ...
- 每天成长一点---WEB前端学习入门笔记
WEB前端学习入门笔记 从今天开始,本人就要学习WEB前端了. 经过老师的建议,说到他每天都会记录下来新的知识点,每天都是在围绕着这些问题来度过,很有必要每天抽出半个小时来写一个知识总结,及时对一天工 ...
- 【前端】Web前端学习笔记【2】
[2016.02.22至今]的学习笔记. 相关博客: Web前端学习笔记[1] 1. this在 JavaScript 中主要有以下五种使用场景 在全局函数调用中,this 绑定全局对象,浏览器环境全 ...
- 【前端】Web前端学习笔记【1】
... [2015.12.02-2016.02.22]期间的学习笔记. 相关博客: Web前端学习笔记[2] 1. JS中的: (1)continue 语句 (带有或不带标签引用)只能用在循环中. ( ...
随机推荐
- jQuery ajax的traditional参数的作用///////////////////////////////////zzzzzzzzzzz
jQuery ajax的traditional参数的作用 i33 发布时间: 2013/04/03 10:05 阅读: 9859 收藏: 9 点赞: 1 评论: 0 一般的,可能有些人在一个参数有多个 ...
- Java中Comparable和Comparator接口区别分析
Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...
- 浅谈在静态页面上使用动态参数,会造成spider多次和重复抓取的解决方案
原因: 早期由于搜索引擎蜘蛛的不完善,蜘蛛在爬行动态的url的时候很容易由于网站程序的不合理等原因造成蜘蛛迷路死循环. 所以蜘蛛为了避免之前现象就不读取动态的url,特别是带?的url 解决方案: 1 ...
- SSM——(一)
入职第一天,项目经理要求利用SSM+MySQL做一个表单的CRUD:之前没用过mybatis,恶补了一下:http://www.jb51.net/article/70923.htm. spring三层 ...
- 推荐一篇好文:OSG OSGearth vs2010编译
链接:http://weibo.com/p/2304189447a8480102v2c2 此文作者把用到的相关代码包放在:http://pan.baidu.com/s/1qW9a4zU 按照步骤操作完 ...
- Nop源码分析三
程序的初始化工作和Ioc工作已经做完,nop默认引擎已经初始化. 下面在回到global文件的启动方法Application_Start()中, 1,继续分析下面的代码: var dependency ...
- python学习笔记之类class(第六天)
参考文档: 1.金角大王博客:http://www.cnblogs.com/alex3714/articles/5188179.html ...
- angularJS——ng-bind指令与插值的区别
在AngularJS中显示模型中的数据有两种方式: 一种是使用花括号插值的方式: <p>{{text}}</p> 另一种是使用基于属性的指令,叫做ng-bind: <p ...
- Java 序列化Serializable详解
Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...
- postman插件安装教程
第一步: 第二步: 第三步: 这样就可以了. 插件下载链接: http://pan.baidu.com/s/1eRVLMpk 密码: 49vb