JS创建对象的方式有几种
相信但凡作为一个前端工程师,都被面试到过这个面试题目,HR考察的就是对oop思想的理解。
作为一个从后端转过来的怂逼,oop一直是心中的永远的痛啊。
这几天一直在通读js高级程序设计,重复理解js创建对象的几种方式,以及原型链和constructor等关键点。
谈到创建对象,我们要从最原始的方式说起,也是最简单的方式,就是直接创建一个Object实例,然后添加属性和方法。
1、简单方式
var o=new Object();
o.name='Lucy';
o.age="20";
o.job = "doctor";
o.showName=function(){
console.log(this.name);
}
简单方式不仅有这种Object构造函数形式,还有对象字面量
var o = {
name:"Lucy",
age:20,
job:"doctor",
sayName: function () {
console.log(this.name);
}
}
这种写法看上去没啥问题,但是在创建多个p,就需要重复的代码,给p添加属性和方法,所以这种写法终究还是不算通用。所以后面就干脆把创建对象的过程抽象出来了,就有了工厂模式。
2、工厂模式
function createPerson(name,age,job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.showName = function(){
console.log(this.name);
}
return o;
}
var p = createPerson('wly','23','前端工程师');
p.showName();
alert(p.constructor == createPerson); //false
alert(p instanceof createPerson); //false
现在可以通过调用这个函数,无数次创建对象了,但是却并不能确切地知道对象的类型。因为ECMAScript的构造函数可用来创建特定类型的对象,所以构造函数模式就出现了。
3、构造函数模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayInfo= function(){
console.log(this.name +"," + this.age + "," + this.job);
}
}
var p1 = new Person('lily','23','前端工程师');
var p2 = new Person('lucy','24','前端工程师');
alert(p1.constructor == Person); //true
alert(p2.constructor == Person); //true
alert(p1 instanceof Person); //true
alert(p2 instanceof Person); //true
alert(p1 instanceof Object); //true
alert(p2 instanceof Object); //true
alert(p1.sayInfo == p2.sayInfo); //false
构造函数模式最大的问题:同一构造函数的不同实例的相同方法是不一样的。

p1,p2都有个constructor属性,该属性指向的就是person。而对象的constructor属性本来就是用来标识对象类型的。不过检测对象类型,还是用instanceof比较好些。至于其中的_prototo__,constructor以后另做详解。
那构造函数又有什么缺点呢,p1和p2都有sayInfo方法,但是是不同实例的同名函数,所以是不相等的( alert(p1.sayInfo == p2.sayInfo) 是false),也就是说构造函数的每个方法事实上是在每个实例中重新重建了一遍,所以难免有点浪费内存。
![]() |
后面就干脆把sayInfo拎出来,成为下面这个样子。
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayInfo= sayInfo;
}
function sayInfo(){
console.log(this.name +"," + this.age + "," + this.job);
}
var p1 = new Person('lily','23','前端工程师');
var p2 = new Person('lucy','24','前端工程师');
alert(p1.sayInfo == p2.sayInfo); //true
![]() |
这儿其实就是p1和p2共享了在全局作用域的sayInfo函数。但是如果我们定义这个全局函数只是为了给某个对象调用,是不是有点奇怪。假设这个Person对象有多个方法,那岂不是要定义多个全局函数。
4、原型模式
function Person(){}
Person.prototype.name = "lily";
Person.prototype.age = 12;
Person.prototype.job = "doctor";
Person.prototype.friends = ["Tom","Lucy"];
Person.prototype.sayName = function(){
console.log(this.name);
};
var a = new Person();
var b = new Person();
a.friends.push("Jack");
console.log(a.friends); //"Tom","Lucy","Jack"
console.log(b.friends); //"Tom","Lucy","Jack"
console.log(a.friends == b.friends) //true
我们的初衷是像这样在所有实例共享属性和方法,我们无话可说,但是一般很少会这样用,因为实例应该拥有自己的全部的属性,这也是为啥很少有人用原型模式的原因。
5、构造模式和原型模式组合使用
创建对象最常见的方式,就是组合使用构造函数模式和原型模式。构造函数用来定义实例属性,原型模式用来定义方法和共享属性。每个实例都会有自己的一份实例属性的副本,但同时又可以共享对方付的引用。
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Tom","Lucy"];
}
Person.prototype = {
constructor : Person,
sayName:function(){
alert(this.name);
}
}
var a = new Person("lily",12,"doctor");
var b = new Person("lucy",23,"teacher");
a.friends.push("Jack");
console.log(a.friends); //"Tom","Lucy","Jack"
console.log(b.friends); //"Tom","Lucy"
console.log(a.friends == b.friends) //false
console.log(a.sayName == b.sayName) //true
独立的friends属性,共享的sayName,这是定义引用类型的一种默认模式。
还有两种方式:寄生构造函数模式 、稳妥构造函数模式,我认为有需要可以去了解下,感觉这两种模式只是在特定情况才会去使用,一般是很少会用到的,着重点应该前面5个的演变历程。
JS创建对象的方式有几种的更多相关文章
- js创建对象的方式 三种
1. 使用直接量创建1个对象: var aobj = { x : 10, y : function(){ console.log("aobj--> "+this.x); } ...
- JS创建对象的方式
1.采用直接量创建方式:系统会使用new方式自动创建对象 var o = {x:1,y:2,z:2}; 2.采用new关键字创建对象:采用构造函数创建对象 var o = new Object();/ ...
- javascript(js)创建对象的模式与继承的几种方式
1.js创建对象的几种方式 工厂模式 为什么会产生工厂模式,原因是使用同一个接口创建很多对象,会产生大量的重复代码,为了解决这个问题,产生了工厂模式. function createPerson(na ...
- JS高级---三种创建对象的方式
JS高级---三种创建对象的方式 字面量的方式 (实例对象) 调用系统的构造函数 自定义构造函数方式 //创建对象---->实例化一个对象,的同时对属性进行初始化 var per=new Per ...
- JS创建对象的几种方式整理
javascript是一种“基于prototype的面向对象语言“,与java有非常大的区别,无法通过类来创建对象.那么,既然是面象对象的,如何来创建对象呢? 一:通过“字面量”方式创建对象 方法:将 ...
- js几种创建对象的方式
javascript是一种“基于prototype的面向对象语言“,与java有非常大的区别,无法通过类来创建对象.那么,既然是面象对象的,如何来创建对象呢? 一.通过”字面量“方式创建. 方法:将成 ...
- 对JS关于对象创建的几种方式的整理
最近一直在看JS高级程序设计这本书,有空来梳理一下几种创建对象的方式.话不多说,直接步入正题. 第一种:Object构造函数创建 var Person = new Object();Person.na ...
- js创建对象的多种方式及优缺点
在js中,如果你想输入一个的信息,例如姓名,性别,年龄等,如果你用值类型来存储的话,那么你就必须要声明很多个变量才行,变量声明的多了的话,就会造成变量污染.所以最好的方式就是存储到对象中.下面能我就给 ...
- JS继承以及继承的几种实现方式总结
传统面向对象语言:继承是类与类之间的关系. 而在js中由于es6之前没有类的概念,所以继承是对象与对象之间的关系. 在js中,继承就是指使一个对象有权去访问另一个对象的能力. 比如:比如对象a能够访问 ...
随机推荐
- ASP.NET——视频总结
ASP.NET的视频很早就看完了,但一直还没顾上总结.虽然在备战软考,学习任务很重,但是阶段的总结还是不要推太久了,不然也就起不到总结的效果了.在看视频之前,虽然已经做过了新闻发布系统,但是对B/S一 ...
- role management
role management https://panjiachen.github.io/vue-element-admin/#/permission/page
- hdu 1426 Sudoku Killer (dfs)
Sudoku Killer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- Ddos攻击防护
Ddos攻击防护 首先我们说说ddos攻击方式,记住一句话,这是一个世界级的难题并没有解决办法只能缓解 DDoS(Distributed Denial of Service,分布式拒绝服务)攻击的主要 ...
- 洛谷树剖模板题 P3384 | 树链剖分
原题链接 对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树 剩下的就和树剖一样了 #include< ...
- 雅礼集训 Day3 T2 u 解题报告
u 题目背景 \(\frac 14\) 遇到了一道水题,完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了一眼就切掉了这题,嘲讽了\(\frac 14\)一番就离开了. ...
- PL/SQL 查询结果集直接修改数据
使用t.rowid,查询可以直接在查询结果中修改提交 SELECT t.rowid,t.* from UC_ROLE t where ROLE_NAME like '% %'
- 怎么用tomcat对socket接口的程序进行调试
对socket(套接字)的demo方法大多都是用main方法进行测试的,那如何用tomcat进行测试呢? 这里需要借助一个工具:工具的名字是:Sockettool.exe .下图是该工具的内容.连上监 ...
- maven使用nexus服务器
1.找到maven的安装路径,例如:C:\apache-maven-3.3.9 打开conf目录下的settings.xml文件 2.在<servers>节点下,配置 <server ...
- 使用java mail的网易smtp协议 发送邮件
package com.enation.newtest; import java.security.GeneralSecurityException; import java.util.Propert ...

