学习javascript面向对象 掌握创建对象的9种方式


Posted in Javascript onJanuary 04, 2016

本文为大家分享了javascript创建对象的9种方式,供大家参考,具体内容如下

【1】使用Object构造函数
[缺点]使用同一个接口创建很多对象,会产生大量重复代码

var person = new Object();
  person.name = "Nicholas";
  person.age = 29;
  person.job = "Software Engineer";
  person.sayName = function(){
  alert(this.name);

}

【2】使用对象字面量
[缺点]使用同一个接口创建很多对象,会产生大量重复代码

var person = {
  name: "Nicholas",
  age : 29,
  job: "Software Engineer",
  sayName: function(){
    alert(this.name);
  }
};

【3】工厂模式:抽象了创建具体对象的过程,考虑到ECMAScript中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节

[缺点]解决了创建多个相似对象的问题,但没有解决对象识别的问题

function createPerson(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 = createPerson('Nicholas',29,'software Engineer');
var person2 = createPerson('greg',27,'doctor');

【4】构造函数模式:没有显式地创建对象,直接将属性和方法赋给了this对象,没有return语句

[缺点]每个方法都要在每个实例上重新创建一遍

function Person(name,age,job){
  this.name = name;
  this.age = age;
  this.jog = job;
  this.sayName = function(){
    alert(this.name);
  };
  //与声明函数在逻辑上是等价的
  //this.sayName = new Function('alert(this.name)');

}
var person1 = new Person("Nicholas",29,"software Engineer");
var person2 = new Person("Greg",27,"doctor");

【4.1】构造函数拓展模式:把函数定义转移到构造函数外部
[缺点1]在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实
[缺点2]若对象需要定义很多方法,就要定义很多全局函数,这个自定义引用类型就没有封装性可言

function Person(name,age,job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = sayName;
}
function sayName(){
  alert(this.name);
}
var person = new Person('小火柴','20','student')
person.sayName();
console.log(Person);

【5】原型模式:我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,prototype就是通过调用构造函数而创建的对象实例的原型对象

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();
person1.sayName();//"Nicholas"
var person2 = new Person();
person2.sayName();//"Nicholas"
alert(person1.sayName == person2.sayName);//true

【5.1】更简单的原型模式:为了减少不必要的输入,也为了从视觉上更好地封装原型的功能,用一个包含所有属性和方法的对象字面量来重写整个原型对象。
[缺点]以这种方式重设constructor属性会导致它的[[Enumerable]]特性被设置为true,默认情况下原生的constructor属性是不可枚举的

function Person(){};
Person.prototype = {
  constructor : Person,
  name: "Nicholas",
  age: 29,
  job: "software Engineer",
  sayName : function(){
    alert(this.name);
  }
};

【5.2】解决enumerable问题的原型模式

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
});

[原型模式缺点1]重写原型对象切断了现有原型与已存在对象实例之间的联系,它们引用的仍是最初的原型。

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

[原型模式缺点2]引用类型属性的共享性问题突出

function Person(){}
Person.prototype = {
  constructor: Person,
  name: "Nicholas",
  age: 29,
  job: "Software Engineer",
  friend : ["shelby","Court"],
  sayName: function(){
    alert(this.name);
  }
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends);//["shelby","Court","Van"];
alert(person2.friends);//["shelby","Court","Van"];
alert(person1.friends === person2.friends);//true

【6】组合模式:组合使用构造函数模式和原型模式是创建自定义类型的最常见方式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。这种混成模式还支持向构造函数传递参数,是用来定义引用类型的一种默认模式

function Person(name,age,job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.friends = ["shelby","Court"];
}
Person.prototype = {
  constructor: Person,
  sayName : function(){
    alert(this.name);
  }  
}
var person1 = new Person("Nicholas",29,"Software Engineer");
var person2 = new Person("Greg",27,"Doctor");
person1.friends.push("Van");
alert(person1.friends);// ["shelby","Court","Van"];
alert(person1.friends);// ["shelby","Court"];
alert(person1.friends === person2.friends);//false
alert(person1.sayName === person2.sayName);//true

【7】动态原型模式:把所有信息都封装在构造函数中,通过在构造函数中初始化原型(仅在必要情况下),又保持了同时使用构造函数和原型的优点。换句话说,可以通过检查某个存在的方法是否有效,来决定是否要初始化原型。

[注意]使用动态原型模式时,不能使用对象字面量重写原型。如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新实例之间的联系

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("Nicholas",29,"Software Engineer");
friend.sayName();

【8】寄生构造函数模式:创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象

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("Nicholas",29,"Software Engineer");
friend.sayName();//"Nicholas"

【寄生构造函数模式应用】创建一个具有额外方法的特殊数组。由于不能直接修改Array构造函数,因此可以使用这个模式

function SpecialArray(){
  //创建数组
  var values = new Array();
  //添加值
  values.push.apply(values,arguments);
  //添加方法
  values.toPipedString = function(){
    return this.join('|');
  };
  //返回数组
  return values;
}
var colors = new SpecialArray("red","blue","green");
alert(colors.toPipedString());//"red|blue|green"

【9】稳妥构造函数模式:所谓稳妥对象指没有公共属性,而且其方法也不引用this的对象。稳妥对象最适合在一些安全环境中(这些环境会禁止使用this和new)或者在防止数据被其他应用程序改动时使用。

function Person(name,age,job){
  //创建要返回的对象
  var o = new Object();
  //可以在这里定义私有变量和函数
  //添加方法
  o.sayName = function(){
    alert(name);
  };
  //返回对象
  return o;
}
//在稳妥模式创建的对象中,除了使用sayName()方法之外,没有其他方法访问name的值
var friend = Person("Nicholas",29,"Software Engineer");
friend.sayName();//"Nicholas"

以上就是javascript创建对象的九种方式,希望对大家的学习有所帮助。

Javascript 相关文章推荐
运用jquery实现table单双行不同显示并能单行选中
Jul 25 Javascript
JavaScript常用对象的方法和属性小结
Jan 24 Javascript
javascrpt绑定事件之匿名函数无法解除绑定问题
Dec 06 Javascript
IE中的File域无法清空使用jQuery重设File域
Apr 24 Javascript
js获取网页可见区域、正文以及屏幕分辨率的高度
May 15 Javascript
JavaScript各类型的关系图解
Oct 16 Javascript
JavaScript下的时间格式处理函数Date.prototype.format
Jan 27 Javascript
javascript 内置对象及常见API详细介绍
Nov 01 Javascript
javascript笔记之匿名函数和闭包
Feb 06 Javascript
JavaScript使用math.js进行精确计算操作示例
Jun 19 Javascript
微信小程序实现手指触摸画板
Jul 09 Javascript
详解vue移动端项目代码拆分记录
Mar 15 Javascript
jQuery自动完成插件completer附源码下载
Jan 04 #Javascript
学习javascript面向对象 理解javascript对象
Jan 04 #Javascript
基于JavaScript实现移除(删除)数组中指定元素
Jan 04 #Javascript
实例代码详解javascript实现窗口抖动及qq窗口抖动
Jan 04 #Javascript
javascript基础语法学习笔记
Jan 04 #Javascript
封装好的javascript前端分页插件pagination
Jan 04 #Javascript
详解javascript的变量与标识符
Jan 04 #Javascript
You might like
用PHP实现Ftp用户的在线管理的代码
2007/03/06 PHP
php获取Google机器人访问足迹的方法
2015/04/15 PHP
php is_writable判断文件是否可写实例代码
2016/10/13 PHP
PHP基于PDO扩展操作mysql数据库示例
2018/12/24 PHP
在 Laravel 6 中缓存数据库查询结果的方法
2019/12/11 PHP
url 特殊字符 传递参数解决方法
2010/01/01 Javascript
js下写一个事件队列操作函数
2010/07/19 Javascript
基于jquery的滑动样例代码
2010/11/20 Javascript
基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
2013/04/26 Javascript
jquery实现的下拉和收缩效果示例
2014/08/21 Javascript
原生JavaScript实现合并多个数组示例
2014/09/21 Javascript
jquery处理json对象
2014/11/03 Javascript
jquery+json实现数据二级联动的方法
2015/11/28 Javascript
js格式化输入框内金额、银行卡号
2016/02/01 Javascript
vue实现ToDoList简单实例
2017/02/07 Javascript
详谈js中window.location.search的用法和作用
2017/02/13 Javascript
利用node.js写一个爬取知乎妹纸图的小爬虫
2017/05/03 Javascript
Vue分页器实现原理详解
2019/06/28 Javascript
微信小程序开发常见问题及解决方案
2019/07/11 Javascript
[26:52]LGD vs EG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python编程二分法实现冒泡算法+快速排序代码示例
2018/01/15 Python
python matlibplot绘制3D图形
2018/07/02 Python
pycharm 解除默认unittest模式的方法
2018/11/30 Python
python实现生成Word、docx文件的方法分析
2019/08/30 Python
Python列表倒序输出及其效率详解
2020/03/04 Python
记录模型训练时loss值的变化情况
2020/06/16 Python
用python读取xlsx文件
2020/12/17 Python
乌克兰网上服装店:Bolf.ua
2018/10/30 全球购物
新西兰网上购物,折扣店:BestDeals.co.nz
2019/03/20 全球购物
美国时尚假发购物网站:Wigsbuy
2019/04/06 全球购物
德国苹果商店:MacTrade
2020/05/18 全球购物
描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理
2015/03/25 面试题
学生会竞选演讲稿学习部
2014/08/25 职场文书
盲山观后感
2015/06/11 职场文书
详解MindSpore自定义模型损失函数
2021/06/30 Python
在MySQL中你成功的避开了所有索引
2022/04/20 MySQL