js中常见的创建对象的方法
前两天好好的把高程对象那一块又读了下,顺便写点笔记。补一句:代码都测试过了,应该没有问题的。可以直接拿到控制台跑!
1.工厂模式
function person(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
}
return o;
}
var person1 = person('Nicholas', 29, 'Software Engineer');
var person2 = person('tangyuhui', 30, 'bigboss');
工厂模式解决了创建多个相似对象的问题,但是没有解决对象识别的问题(怎样知道一个对象的类型)。
2.构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
} ;
}
var person1 = new Person('Nicholas', 29, 'Software Engineer');
var person2 = new Person('tangyuhui', 30, 'bigboss');
相对于工厂模式,存在不同的地方是:
(1)没有显示地创建对象
(2)直接将属性和方法赋给了this对象
(3)没有return语句
注意:使用构造函数创建新实例,实际上会经历以下四个阶段:
(1)创建一个新对象
(2)将构造函数的作用域赋值给新对象(因此this指向了这个新对象)
(3)执行构造函数中的代码(为这个新对象添加属性)
(4)返回新对象(这里是没有显示地return才会返回新对象)
注意:构造函数的缺点是实例上的方法不是相等的,即不同实例上的同名函数是不相等的。
person1.sayName === person2.sayName //false
3.原型模式
function Person() {};
Person.prototype.name = 'Nicholas';
Person.prototype.age = 29;
Person.prototype.job = 'Software Engineer';
Person.prototype.sayName = function() {
alert(this.name);
} ;
var person1 = new Person();
var person2 = new Person();
person1.sayName === person2.sayName //true
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象是保存可以由特定类型的所有实例共享的属性和方法。
好处:可以让所有对象实例共享它所包含的属性和方法。
实例----原型----构造函数之间的关系如下图:

当然这里有一个更简便的写法:
function Person() {};
Person.prototype = {
constructor: Person,
name: 'Nicholas',
age: 29,
job: 'Software Engineer',
sayName: function() {
alert(this.name);
}
}
这里会有一个问题,这种方式重设constructor属性会导致它的[[Enumerable]]特性被设置为true,所以还有另外一种写法:
function Person() {};
Person.prototype = {
name: 'Nicholas',
age: 29,
job: 'Software Engineer',
sayName: function() {
alert(this.name);
}
}
Object.defineProperty(Person.prototype, 'constructor', {
enumerable: false,
value: Person
})
这里有一点要注意:如果要重写原型对象,一定要先重写后实例化,不然实例和原型之间就断了联系。类似下面的代码,会出错的:
function Person() {};
var friend= new Person();
Person.prototype = {
constructor: Person,
name: 'Nicholas',
age: 29,
job: 'Software Engineer',
sayName: function() {
alert(this.name);
}
}
friend.sayName();//Error
原理图如下:

原型对象代码量是减少了,但是它缺点也是比较突出的,问题就出在引用类型是按引用传递的。看代码
function Person(){};
Person.prototype = {
constructor: Person,
name:'Nicholas',
age: 29,
job: 'Software Engineer',
friends: ['zhangsan','lisi'],
sayName: function(){
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
person1.friends.push('wanger');
console.log(person1.friends); //zhangsan,lisi,wanger
console.log(person2.friends); //zhangsan,lisi,wanger
4.组合使用构造函数模式和原型模式
单独使用原型模式还是有一点问题,创建自定义类型的常见方式,就是使用构造函数模式与原型模式。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.firends = ['mayun', 'mahuateng']
}
Person.prototype = {
constructor: Person,
sayName: function() {
alert(this.name)
}
}
var person1 = new Person('zhangsan', 29, '厨师');
var person2 = new Person('lisi', 30, '工程师');
person1.firends.push('wangwei');
console.log(person1.firends); //mayun, mahuateng, wangwei
console.log(person2.firends); //mayun, mahuateng
console.log(person1.sayName === person2.sayName); //true
5.动态原型模式
如果想把所有的信息封装在构造函数中,就可以使用该模式。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
if (typeof this.sayName !== 'function') {
Person.prototype.sayName = function(){
alert(this.name);
}
}
}
var friend = new Person('zhangsan', 29, '大佬');
6.寄生构造函数模式
function Person(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
}
return o;
}
var friend = new Person('zhangsan', 40, '计生办');
friend.sayName() //zhangsan
这种模式和工厂函数模式很像,只是使用new实例化对象,使用new构造函数实例化函数时会4个过程,如果没有指定返回值时,默认返回的是this,但也可以显示的return。这里就使用了该特性。这种模式不常用,会用到该模式,真的不常用。反正我没怎么用过。
7.稳妥构造函数模式
所谓稳妥对象,指的是没有公共属性,而且其他方法也不引用this,稳妥对象最合适在一些安全的环境中或者防止数据被篡改的程序中使用。
function Person(name, age, job) {
var o = new Object();
//定义私有变量和函数
//添加方法
o.sayName = function() {
alert(name);
}
return o;
}
var friend = Person('zhangsan', 40, '计生办');
friend.sayName() //zhangsan 只有该方法才能访问到name的值
这里需要注意的是寄生构造函数模式和稳妥构造函数模式创建的实例对象与构造函数没有什么关系。
js中常见的创建对象的方法的更多相关文章
- js中常见的创建对象的方法(1)
工厂模式:抽象了创建具体对象的过程 function createPerson(name, age, job){ var obj = new Object(); obj.name = name; ob ...
- js 中常见的深拷贝的方法
建议最简单的第一种 1.通过 JSON 对象实现深拷贝 this.data = JSON.parse(JSON.stringify(this.vm.$store.state.security.menu ...
- JS 中常见数组API使用方法(join、concat、slice、splice、reverce)
刚接触前端不久,个人觉得学习程序还是需要经常总结的.下面是我的一些知识的归纳总结,如果哪里说得不对的还请各位大神指点! 1.to str (1)String(arr)将数组中的每个元素转为字符串并用逗 ...
- JS中常见的几种继承方法
1.原型链继承 // 1.原型链继承 /* 缺点:所有属性被共享,而且不能传递参数 */ function Person(name,age){ this.name = name this.age = ...
- js中常见的问题
js中常见的问题 原文链接 1.js获取select标签选中的值 原生js var obj = document.getElementByIdx_x(”testSelect”); //定位id var ...
- JS中常见算法问题
JS中常见算法问题 1. 阐述JS中的变量提升(声明提前) 答:将所有的变量提升当当前作用域的顶部,赋值留在原地.意味着我们可以在某个变量声明前就使用该变量. 虽然JS会进行变量提升,但并不会执行真正 ...
- js中json法创建对象(json里面的:相当于js里面的=)
js中json法创建对象(json里面的:相当于js里面的=) 一.总结 json里面的:相当于js里面的= 4.json创建js对象解决命名冲突:多个人为同一个页面写js的话,命名冲突就有可能发生, ...
- JS中常见的几种报错类型
1.SyntaxError(语法错误) 解析代码时发生的语法错误 var 1a; //Uncaught SyntaxError: Invalid or unexpected token 变量名错误 c ...
- 判断js中各种数据的类型方法之typeof与0bject.prototype.toString讲解
提醒大家,Object.prototype.toString().call(param)返回的[object class]中class首字母是大写,像JSON这种甚至都是大写,所以,大家判断的时候可以 ...
随机推荐
- asp.net 退出登陆(解决退出后点击浏览器后退问题仍然可回到页面问题)
代码如下: Session.Abandon(); Response.Redirect("Login.aspx"); 但是这样点点击浏览器的后退仍然可以回到刚才的页面,这可不行,在网 ...
- [记录]js跨域调用mvc ActionResult扩展
背景 最近2个项目中都用到了js跨域访问的知识,2个项目都需要主站与各个分站之间进行数据交互.状态同步等相关操作.浏览器本身是不允许进行跨域访问,在MVC中我们可以扩展一个方法来实现这个功能.在此大家 ...
- bzoj 1414: [ZJOI2009]对称的正方形
Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一 ...
- java判断字符串中是否含有中文
/** * 判断字符串中是否含有中文 */ public static boolean isCNChar(String s){ boolean booleanValue = false; for(in ...
- 关于cookie的一些事
关于cookie的一些事转自:http://blog.csdn.net/yunnysunny/article/details/7748106 cookie是实现web中用户状态维护的基础.我们常见的s ...
- 对于入门Demo的看法
对于一些以前没有接触过的技术,网上一搜,了解一些介绍信息,原理以及一些代码API的大致了解,接下来应该开始一个小Demo例子. 网上现在好多的教材,多数不知是怎么写的,基本大致一个样,对于初学者没什么 ...
- Python3 引入sqlite3时出现错误:ModuleNotFoundError: No module named '_sqlite3'
在Python3 中内置了SQLite3,但是在编译安装完之后执行: import sqlite3 出现错误: ModuleNotFoundError: No module named '_sqlit ...
- c++官方文档-模版类
#include <iostream> using namespace std; template<class T> class MyPair { private: T t[] ...
- 写下thinkphp5和thinkphp3.2的不同
只列出一些自己的直观感受 1 引入了命令行,估计来源是laravel,前阵子刚练手完laravel5.0的系统, 感觉thinkphp5的命令行和laravel的很像 2 引入了路由,来源估计也是la ...
- 代码:cookie(一个广告展示例子)
这个小例子的要求是: 用户第一次进入,显示大图,2秒后大图动画关闭,再把小图动画展开: 用户再次进入后,只显示静态小图. 做法: 定义一个容器 .img201512ad,宽高写死:1190x70.—— ...