Created by Yiyi_coding
Last edited at 2016年7月22日

JavaScript创建对象的几种方式?

第一种: 对象字面量的方式

var person = {firstName:"Mark",lastName:"Yun",age:25,sayHello:function(){alert("Hello!")}};

第二种: 用function来模拟无参的构造函数

function Person(){};
var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class
person.name="Mark";
person.age="25";
person.sayHello = function(){alert(person.name+" Hello!");
}

第三种: 用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)

function People(name,age,hobby){this.name=name;//this作用域:当前对象this.age=age;this.hobby=hobby;this.sayHello=function(){alert("Hello,我叫"+this.name);}}
var yiyi =new People("Yiyi",25,"coding");//实例化、创建对象
yiyi.sayHello();//调用eat方法

以上两种构造函数模式,把属性封装在一个对象里面。可以进行如下操作实例话对象:

  var yiyi = new People("Yiyi","18","coding");var shuzi = new People("Shuzi","18","eating");

这时yiyi和shuzi会自动含有一个constructor属性,指向它们的构造函数People,即yiyi.constructor == People

构造函数存在的问题:构造函数方法很好用,但是存在一个浪费内存的问题。
上例People中,对于每一个实例对象,sayHello()方法都是一模一样的,每一次生成一个实例,都必须为重复的内容,多占用一些内存。这样既不环保,也缺乏效率。console.log(yiyi.sayHello == shuzi.sayHello); //false,故可判断内存地址不同
不能让sayHello()方法在内存中只生成一次,然后所有实例都指向那个内存地址呢?回答是可以的,这就是下面提到的混合方式来创建(构造函数与原型混合)

第四种: 用工厂方式来创建(内置对象)

先扔个链接吧,有时间再总结工厂模式.

第五种: 用原型方式来创建(prototype)

function Dog(){}
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){alert(this.name+"是个吃货");}
var xiaobai = new Dog();
xiaobai.eat();

第六种: 用混合方式来创建(构造函数与原型混合)

Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。我们可以利用这一点,把那些不变的属性和方法,直接定义在prototype对象上,如下:

function People(name,age){//构造函数this.name = name;this.age = age; }
People.prototype.sayHello = function(){//原型模式alert("Hello,我是"+this.name);}
var yiyi =new People("Yiyi",25);
var shuzi = new People("Shuzi",18);
console.log(yiyi.sayHello == shuzi.sayHello);//true,故可判断内存地址相同,节约了内存!

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

1⃣️ isPrototypeOf()

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

console.log(People.prototype.isPrototypeOf(yiyi));//true
2⃣️ hasOwnProperty()

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

console.log(yiyi.hasOwnProperty("name"));//true,本地属性
console.log(yiyi.hasOwnProperty("sayHello"));//false,继承自prototype对象的属性
3⃣️ in运算符遍历对象所有的属性
for(var prop in yiyi) { console.log("yiyi["+prop+"]="+yiyi[prop]); }
***result:***
yiyi[name]=Yiyi
yiyi[age]=25
yiyi[sayHello]=function (){//原型模式alert("Hello,我是"+this.name);}

JavaScript如何实现继承?

第一种:构造继承

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

function People(name,age){this.name = name;this.age = age;
}
function Women(danceStyle){this.danceStyle = danceStyle;People.apply(this, arguments);//将父对象(People)的构造函数绑定在子对象(Women)上,实例化子对象后可以访问父对象的属性,如下图怪异现象。
}

第二种:原型继承

将Women的prototype对象,指向一个People的实例,那么所有Women的实例,就能继承People了。

function People(name,age){this.name = name;this.age = age;
}
function Women(danceStyle){this.danceStyle = danceStyle;
}
Women.prototype = new People();//将Women的prototype对象指向一个People的实例,它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。
Women.prototype.constructor = Women;//任何一个prototype对象都有一个constructor属性,指向它的构造函数。
如果没有"Women.prototype = new People()"这一行,Women.prototype.constructor是指向Women的;
加了这一行以后,Women.prototype.constructor指向People。

更重要的是,每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。因此,在运行”Women.prototype = new People();”这一行之后,shuzi.constructor也指向People!这显然会导致继承链的紊乱(shuzi明明是用构造函数Women生成的),因此我们必须手动纠正,将Women.prototype对象的constructor值改为Women。这就是第二行的意思。

*编程时务必要遵守: 如果替换了prototype对象, o.prototype = {};,那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。  o.prototype.constructor = o;

第三种:直接继承prototype

改写上述栗子:

function People(){}
People.prototype.sayHello = function(){alert("Hello!")}function Women(danceStyle){this.danceStyle = danceStyle;
}
Women.prototype = People.prototype;//将Women的prototype对象指向People的prototype对象,这样就完成了继承。

与前一种方法相比,这样做的优点是效率比较高(不用执行和建立People的实例了),比较省内存。
缺点是 Women.prototype和People.prototype现在指向了同一个对象,那么任何对Women.prototype的修改,都会反映到People.prototype中。参考下图,修改Women.prototype的时候也将People.prototype修改掉了!!!

第四种:实例继承

由于”直接继承prototype”存在上述的缺点,所以就有第四种方法,利用一个空对象作为中介。

var emptyObj = function(){};emptyObj.prototype = People.prototype;Women.prototype = new emptyObj();Women.prototype.constructor = Women;

empty是空对象,所以几乎不占内存。这时,修改Cat的prototype对象,就不会影响到Animal的prototype对象。
我们将上面的方法,封装成一个函数,便于使用:

function extend(Child, Parent) {var emptyObj = function(){};emptyObj.prototype = Parent.prototype;Child.prototype = new emptyObj();Child.prototype.constructor = Child;Child.uber = Parent.prototype;//为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。(uber是一个德语词,意思是"向上"、"上一层"。)这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。不写也能调用的吧?}

第五种:拷贝继承

简单说,就是把父对象的所有属性和方法,拷贝进子对象,这样也能够实现继承。

//这个函数的作用,就是将父对象的prototype对象中的属性,一一拷贝给Child对象的prototype对象。
function extend2(Child, Parent) {var p = Parent.prototype;var c = Child.prototype;for (var i in p) {c[i] = p[i];}c.uber = p;}

快捷键

  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

JavaScript 面向对象编程浅谈相关推荐

  1. 浅谈JavaScript 面向对象编程[转]

    这周心血来潮,翻看了现在比较流行的几个 JS 脚本框架的底层代码,虽然是走马观花,但也受益良多,感叹先人们的伟大-- 感叹是为了缓解严肃的气氛并引出今天要讲的话题,"javascript 面 ...

  2. OOD面向对象设计浅谈

    來源:http://dev.csdn.net/htmls/59/59377.html OOD面向对象设计浅谈 前言 OOD指面向对象设计,在软件设计生命周期中发生于OOA之后期或者之后,OOA与OOD ...

  3. JavaScript 面向对象编程(三) —— 函数进阶 / 严格模式 / 高阶函数 / 闭包 / 浅拷贝和深拷贝

    本篇为 JavaScript 进阶 ES6 系列笔记第三篇,将陆续更新后续内容.参考:JavaScript 进阶面向对象 ES6 :ECMAScript 6 入门 系列笔记: JavaScript 面 ...

  4. 在JavaScript面向对象编程中使用继承(5)

    明天就要回老家去过年了,关于这个"在JavaScript面向对象编程中使用继承"的话题居然还没有说完.如果不完成,留下来一拖就拖到明年去了.所以还是抽空把它写完,今年的事情今年做, ...

  5. 编程浅谈-以一个初出茅庐的Java程序员视角

    编者是一个从事Java开发的普通软件攻城狮,迄今为止,粗粗算来不过刚刚进入编程的世界不过两年,但在这两年的光阴里,每当我抬头仰望星空(苦命加班)时脑海里总有这样一个疑问--"什么是编程&qu ...

  6. JavaScript面向对象编程(2)-- 类的定义

    javascript面向对象编程(2)-- 类的定义 2008-05-29 11:05 by johnson2008, 6196 visits, 收藏, 编辑 最近这一段时间事情太多了,没有时间再继续 ...

  7. 《JavaScript面向对象编程指南》——第1章 引言1.1 回顾历史

    本节书摘来自异步社区<JavaScript面向对象编程指南>一书中的第1章,第1.1节,作者: [加]Stoyan Stefanov 译者: 凌杰 更多章节内容可以访问云栖社区" ...

  8. 《JavaScript面向对象编程指南》——1.3 分析现状

    本节书摘来自异步社区<JavaScript面向对象编程指南>一书中的第1章,第1.3节,作者: [加]Stoyan Stefanov 译者: 凌杰 更多章节内容可以访问云栖社区" ...

  9. (二)Javascript面向对象编程:构造函数的继承

    Javascript面向对象编程:构造函数的继承 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承&q ...

最新文章

  1. Mysql连接数据库的操作
  2. 进程间通信的方式(三):消息队列
  3. docker的文件流处理_Docker数据卷Volume实现文件共享、数据迁移备份(三)--技术流ken...
  4. python跳转到程序顶部_python-如何使Tkinter窗口跳到最前面?
  5. 对已经关闭的的chan进行读写,会怎么样?为什么?
  6. 最大概率法分词及性能測试
  7. Ubuntu中DenyHosts清除黑名单IP地址
  8. python数组拼接concat_Python xarray.concat然后xarray.to_netcdf生成巨大的新文件大小
  9. [Python从零到壹] 十.网络爬虫之Selenium爬取在线百科知识万字详解(NLP语料构造必备技能)
  10. Win10教育版变为企业版
  11. GIT原理,知其然,知其所以然
  12. php函数改变图片大小,php实现修改图片大小的方法
  13. 微型计算机3c认证元器件清单,3C认证产品目录.pdf
  14. Raspbian命令行安装desktop界面
  15. iPhone 电池的正确激活与使用方式
  16. python打造记账本_python实现日常记账本小程序
  17. linux用户目录设置权限设置,为linux目录设置多个用户权限
  18. 关于PlatformIO开发 Arduino,自定义库的设置
  19. 树莓派python工业数据采集系统
  20. html 字体图标 ttf,用FontLab将图标做成字体在网站上显示的方法

热门文章

  1. win10下go mod 与gopath
  2. 2022山东理工大学pta程序设计---实验五(一维数组)详解
  3. 山东标梵讲解文案策划需要的写法
  4. php针式打印机打多张,ppt打印怎么一页打多个
  5. html通过分辨率动态加载css,做响应式页面,响应式和自适应的区别
  6. Easy Crypto 专题总结
  7. java视频直播_java视频直播、聊天室、弹幕、多端适配
  8. 留言板管理系统 jsp + servlet + mysql (2004)
  9. 当你调用setState的时候,发生了什么事?
  10. C++——deque