创建对象

js高程3--第6章面向对象的程序设计--第二节创建对象,批量创建对象有很多种模式,每一种模式都有自己的优点与缺点,搞清楚它们出现的历史原因,优缺点,我们才能使用的更加游刃有余!

本片文章并没有将细节的挖的特别深,重点关注的是每种模式的优缺点,怎么形成的。细节会另写博客总结。

正文开始

我们都知道创建单个对象有两种方法,构造函数字面量的形式。

var obj = new Object(); //构造函数
var obj1 = {}; //字面量

如果我们想要创建多个对象,这两种形式就有明显的缺点:每一个新对象都要手写生成,会产生大量重复的代码!

为了解决这个问题,聪明的程序员开始使用工厂模式

工厂模式

用函数来封装以特定接口创建对象的细节

function createPerson(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.sayName = function(){
alert(this.name);
}
return obj;
}
var zhangsan = creatPerson('zhangsan',18);

优点:解决了创建多个相似对象,代码重复问题

缺点:没有解决对象识别问题,即不知道当前对象的类型,一直都是Object类型

随着javascript的发展,又一个新的模式出现了!

构造函数模式

ECMAScript中的构造函数可以用来创建特定类型的对象。

类似Object,Array这种原生的构造函数,我们可以使用new Object(),new Array()来创建对象类型或者数组类型的对象。

同样我们可以构建自定义类型的构造函数,定义自定义类型的属性和方法。

function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
}
} var zhangsan = new Person('zhangsan',18);

优点:可以使用instanceof,isPrototypeOf用来识别对象的类型

缺点 :每个方法都要在每个实例上重新创建一遍,浪费内存。

有人觉得既然实例的sayName函数的作用相同,就没有必要提前把函数绑定到构造函数中,可以这样

function Person(name,age){
this.name = name;
this.age = age;
this.sayName = sayName;
}
function sayName(){ //变为全局函数
alert(this.name);
}
var zhangsan = new Person('zhangsan',18);

看似很好的解决了每次都重新创建的问题,但是这样又延伸出一个新的让人无法接受的问题,全局变量污染,这样根本没有封装性可言。

very lucky!这些问题都可以通过原型模式解决。

原型模式

function Person(){}

Person.prototype.name = 'zhang';
Person.prototype.age = 18;
Person.prototype.sayName = function(){
alert(this.name);
}

这样每一个实例的__proto__属性引用Person的原型属性地址,共用一个原型对象。

但是上面的写法每次添加属性都要Person.prorotype很麻烦,可以使用下面字面量的形式

function Person(){}

Person.prototype = {
name:'zhang',
age:18,
sayName:function(){
alert(this.name);
}
} var zhang = new Person();

但是字面量的写法会切断原型链,尽管这里使用instanceofisPrototypeOf仍然可以判断实例的类型,

但是我们通过zhang.constructor得到的是Object,而不再是Person了,因为我们改变了Person的原型属性默认的地址,新地址constructor属性是不存在的。

所以为了是原型链完整,可以使用下面的形式

function Person(){}

// 也可在这里直接添加constructor,
// 只不过constructor属性特征跟默认的(不可枚举)是不一样的
Person.prototype = {
name:'zhang',
age:18,
sayName:function(){
alert(this.name);
}
} // 手动添加构造函数属性,保证原型链完整,
Object.defineProperty(Person.prototype,'constructor',{
value:Person,
enumerable:false,
}) var zhang = new Person();

但是,这样还是会有问题,所有的实例都是一样的属性和方法,没有私人属性和方法,这当然不是我们想要的。

解决这个问题很简单,把构造函数模式原型模式混合使用

function Person(name,age){
this.name = name;
this.age = age;
} Person.prototype = {
sayName:function(){
alert(this.name);
}
}
var zhang = new Person(); // 手动添加构造函数属性,保证原型链完整,
Object.defineProperty(Person.prototype,'constructor',{
value:Person,
enumerable:false,
})

Perfect!!!这种组合构造函数和原型模式是目前使用最为广泛的模式,可以说是创建自定义类型的默认模式了。

但是,-_-,哈哈 心中一万只神兽,竟然还有但是!!!

严格面向对象的语言使用者看见这种形式会非常懵逼,说好的封装,竟然不把所有信息封装在构造函数里面,竟然还有独立的原型,wtf!

程序员嘛,多少会有点的强迫症。

动态原型模式

这个模式非常的巧妙,第一次看见非常的兴奋。

function Person(name,age){
this.name = name;
this.age = age;
// 第一次初始化构造函数的时候执行,之后不再执行
// 这里的属性判断随便一个原型属性都可以
if(typeof this.sayName != 'function'){
Person.prototype = {
sayName:function(){
alert(this.name);
}
}
}
} var zhang = new Person();

当得了当~~~,如果不加这个判断,每次实例化都执行一遍原型是不现实的,加个判断完美解决了这个问题,这种解决问题的思想是值得非常借鉴的,可以应用到我们的实际开发中。

寄生构造函数模式

还没有搞明白,待续

稳妥构造函数模式

还没有搞明白,待续

补充

要真正搞清楚对象这一块,需要清楚一下几个知识点:

Object

instanceof

getPrototypeOf

isPrototypeOf

hasOwnProperty

defineProperty

in

本人能力有限,理解的不对的欢迎指正!

js高程3--面向对象的程序设计--创建对象的更多相关文章

  1. 重学js之JavaScript 面向对象的程序设计(创建对象)

    注意: 本文章为 <重学js之JavaScript高级程序设计>系列第五章[JavaScript引用类型]. 关于<重学js之JavaScript高级程序设计>是重新回顾js基 ...

  2. JS_高程6.面向对象的程序设计(2)创建对象_3 构造函数存在的问题

    # 上次讲到用构造函数的模式来创建对象,相对于工厂模式,解决可对象识别的问题. function Person(name,age,job){ this.name=name; this.age=age; ...

  3. JS_高程6.面向对象的程序设计(2)创建对象_1

    一.创建对象的常见方法 (1)Object构造函数创建单个对象,早期的JavaScript开发人员经常使用该模式创建新对象. var person=new Object(); person.name= ...

  4. JS_高程6.面向对象的程序设计(2)创建对象_2 构造函数也是一般函数

    1.构造函数也是一般函数,以下创建一个构造函数. var Person=function(name,age,job){ this.name=name; this.age=age; this.job=j ...

  5. JS_高程6.面向对象的程序设计(1)理解对象

    js的数据属性:P139(1)[[Configurable]](2)[[Enumerable]](3)[[Writable]](4)[[Value]] 使用Object.definerPropert( ...

  6. 《JS高程》创建对象的7种方式(完整版)

    一.理解对象 ECMA-262定义对象:无序属性的集合,其属性可以包含基本值.对象或者属性. 我们可以把 ECMAScript 的对象想象成 散列表:无非就是一组 名值对,其中值可以是数据或函数. 创 ...

  7. 吃透Javascript数组操作的正确姿势—再读《Js高程》

    Javascript中关于数组对象的操作方法比较多也比较杂,正好再次捡起<Javascript高级程序设计>来读,把它们一一总结梳理了一下: 方法类别 方法名称 方法描述 参数 返回值 备 ...

  8. 《JS高程》JS-Object对象整理

    继上篇<JS高程>对象&原型笔记,对JavaScript中的Object对象进行了整理,梳理一遍~ 参考文章:详解Javascript中的Object对象 ------------ ...

  9. Day046--JavaScript-- DOM操作, js中的面向对象, 定时

    一. DOM的操作(创建,追加,删除) parentNode 获取父级标签 nextElementSibling 获取下一个兄弟节点 children 获取所有的子标签 <!DOCTYPEhtm ...

随机推荐

  1. 剑指offer第二版-9.用两个栈实现队列

    描述:使用两个栈实现一个队列.队列中实现尾部插入和头部删除函数. 思路:stack1负责插入,stack2负责弹出,如果stack2为空了,将stack1的元素依次弹出并存放到stack2中,之后对s ...

  2. 这样子来理解C语言中指针的指针

    友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...

  3. 使用gulp构建微信小程序工作流

    前言 刚入门微信小程序的时候,一切都基于微信web开发者工具,没有使用其他框架,也没有工程化的概念.当时做的项目都比较简单,单单用微信web开发者工具倒也得心应手.学了些东西后,就按捺不住地想跳出原生 ...

  4. Java编程思想:文件加锁

    import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; i ...

  5. Uncaught Error: Bootstrap dropdown require Popper.js

    Bootstrap 要求Popper.js 如果安装了Popper.js还报错,肯定就是Popper的问题 https://cdn.bootcss.com/popper.js/1.12.5/umd/p ...

  6. 洛谷 P1463、POI2002、HAOI2007 反素数

    题意: 求最小的$x\in[1,N]$,使得$x$为$g(x)$最大的数 中最小的一个. 分析: 1.$x$不会有超过$10$个不同质因子.理由:$2 \times 3\times 5...\time ...

  7. Excel催化剂开源第47波-Excel与PowerBIDeskTop互通互联之第一篇

    当国外都在追求软件开源,并且在GitHub等平台上产生了大量优质的开源代码时,但在国内却在刮着一股收割小白智商税的知识付费热潮,实在可悲. 互联网的精神乃是分享,让分享带来更多人的受益. 在Power ...

  8. Spring集成Shiro使用小结

    shiro的认证流程 Application Code:应用程序代码,由开发人员负责开发的 Subject:框架提供的接口,代表当前用户对象 SecurityManager:框架提供的接口,代表安全管 ...

  9. linux初学者-磁盘配额篇

    linux初学者-磁盘配额篇 在使用磁盘时,只要有权限,不管什么用户都可以在其中写入数据,但是如果是多人在一个磁盘中写入数据,就会出现争议,如果一个用户将磁盘空间用完,那么其他人无法再使用.如下图所示 ...

  10. Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建

    前言 前面铺垫了这么久,终于要开始写热更新了. Unity游戏热更新包含两个方面,一个是资源的更新,一个是脚本的更新. 资源更新是Unity本来就支持的,在各大平台也都能用.而脚本的热更新在iOS平台 ...