学习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 相关文章推荐
javascript 跳转代码集合
Dec 03 Javascript
分享14个很酷的jQuery导航菜单插件
Apr 25 Javascript
JQuery插入DOM节点的方法
Jun 11 Javascript
jQuery中$this和$(this)的区别介绍(一看就懂)
Jul 06 Javascript
详解JavaScript对象序列化
Jan 19 Javascript
15款最好的Bootstrap在线编辑器
Aug 03 Javascript
AngularJS表单验证中级篇(3)
Sep 28 Javascript
利用express启动一个server服务的方法
Sep 17 Javascript
vue与TypeScript集成配置最简教程(推荐)
Oct 17 Javascript
用react-redux实现react组件之间数据共享的方法
Jun 08 Javascript
分享5个顶级的JavaScript Ajax组件库
Sep 16 Javascript
jQuery实现验证用户登录
Dec 10 jQuery
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
用 PHP5 轻松解析 XML
2006/12/04 PHP
snoopy PHP版的网络客户端提供本地下载
2008/04/15 PHP
基于PHP编程注意事项的小结
2013/04/27 PHP
PHPAnalysis中文分词类详解
2014/06/13 PHP
php中unserialize返回false的解决方法
2014/09/22 PHP
PHP简单的MVC框架实现方法
2015/12/01 PHP
php简单复制文件的方法
2016/05/09 PHP
PHP 500报错的快速解决方法
2016/12/14 PHP
PHP设计模式之单例模式原理与实现方法分析
2018/04/25 PHP
PHP一致性hash分布式算法封装类定义与用法示例
2018/08/04 PHP
30分钟就入门的正则表达式基础教程
2013/02/25 Javascript
javascript写的异步加载js文件函数(支持数组传参)
2014/06/07 Javascript
21个JavaScript事件(Events)属性汇总
2014/12/02 Javascript
JavaScript实现将数组中所有元素连接成一个字符串的方法
2015/04/06 Javascript
完美实现仿QQ空间评论回复特效
2015/05/06 Javascript
js实现文字截断功能
2016/09/14 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
2017/02/14 Javascript
BootstrapTable refresh 方法使用实例简单介绍
2017/02/20 Javascript
vue上传图片组件编写代码
2017/07/26 Javascript
Vue 递归多级菜单的实例代码
2019/05/05 Javascript
详解Vue.js中引入图片路径的几种方式
2019/06/17 Javascript
js实现随机数小游戏
2019/06/28 Javascript
BootstrapValidator验证用户名已存在(ajax)
2019/11/08 Javascript
Bootstrap FileInput实现图片上传功能
2021/01/28 Javascript
python二分法实现实例
2013/11/21 Python
python调用Moxa PCOMM Lite通过串口Ymodem协议实现发送文件
2014/08/15 Python
使用Python绘制图表大全总结
2017/02/11 Python
python查看列的唯一值方法
2018/07/17 Python
Python对象转换为json的方法步骤
2019/04/25 Python
python中bytes和str类型的区别
2019/10/21 Python
Python getattr()函数使用方法代码实例
2020/08/10 Python
使用css3实现的windows8开机加载动画
2014/12/09 HTML / CSS
《列夫托尔斯泰》教学反思
2014/02/10 职场文书
社区党务公开实施方案
2014/03/18 职场文书
先进单位申报材料
2014/12/25 职场文书
Python代码实现双链表
2022/05/25 Python