学习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 相关文章推荐
教你用AngularJS框架一行JS代码实现控件验证效果
Jun 23 Javascript
使用jQuery jqPlot插件绘制柱状图
Dec 18 Javascript
JavaScript中的闭包
Feb 24 Javascript
AngularJS入门教程之AngularJS表达式
Apr 18 Javascript
jQuery实现图像旋转动画效果
May 29 Javascript
Sortable.js拖拽排序使用方法解析
Nov 04 Javascript
详解javascript中对数据格式化的思考
Jan 23 Javascript
js实现3D图片环展示效果
Mar 09 Javascript
浅谈react.js中实现tab吸顶效果的问题
Sep 06 Javascript
详解vue如何使用rules对表单字段进行校验
Oct 17 Javascript
layer.confirm()右边按钮实现href的例子
Sep 27 Javascript
p5.js临摹动态图形实现方法详解
Oct 23 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
Symfony查询方法实例小结
2017/06/28 PHP
PHP设计模式之适配器模式(Adapter)原理与用法详解
2019/12/12 PHP
PHP实现chrome表单请求数据转换为接口使用的json数据
2021/03/04 PHP
Js 获取当前日期时间及其它操作实现代码
2021/03/04 Javascript
jQuery Lightbox 图片展示插件使用说明
2010/04/25 Javascript
使用 JScript 创建 .exe 或 .dll 文件的方法
2011/07/13 Javascript
JS的replace方法详细介绍
2012/11/09 Javascript
使用js 设置url参数
2013/07/08 Javascript
jQuery添加/改变/移除CSS类及判断是否已经存在CSS
2014/08/20 Javascript
jQuery实现响应浏览器缩放大小并改变背景颜色
2014/10/31 Javascript
JavaScript通过this变量快速找出用户选中radio按钮的方法
2015/03/23 Javascript
jquery使用each方法遍历json格式数据实例
2015/05/18 Javascript
详解JavaScript常量定义
2017/01/03 Javascript
JS ES6中setTimeout函数的执行上下文示例
2017/04/27 Javascript
JavaScript html5 canvas实现图片上画超链接
2017/10/20 Javascript
微信小程序swiper实现滑动放大缩小效果
2018/11/15 Javascript
使用Three.js实现太阳系八大行星的自转公转示例代码
2019/04/09 Javascript
Vue 微信端扫描二维码苹果端却只能保存图片问题(解决方法)
2020/01/19 Javascript
微信小程序云函数添加数据到数据库的方法
2020/03/04 Javascript
跟老齐学Python之通过Python连接数据库
2014/10/28 Python
Python随机生成信用卡卡号的实现方法
2015/05/14 Python
python获取一组数据里最大值max函数用法实例
2015/05/26 Python
解析Python中的生成器及其与迭代器的差异
2016/06/20 Python
win10环境下python3.5安装步骤图文教程
2017/02/03 Python
Python函数__new__及__init__作用及区别解析
2020/08/31 Python
网络、C以及其他硬件方面的面试题
2016/08/23 面试题
盛大二次面试题
2016/11/18 面试题
工程业务员工作职责
2013/12/07 职场文书
幼儿园毕业教师感言
2014/02/21 职场文书
公司司机岗位职责范本
2014/03/03 职场文书
建筑安全生产目标责任书
2014/07/23 职场文书
机关党员四风问题个人整改措施
2014/10/26 职场文书
五星红旗迎风飘扬观后感
2015/06/17 职场文书
刚学完怎么用Python实现定时任务,转头就跑去撩妹!
2021/06/05 Python
Netty分布式客户端接入流程初始化源码分析
2022/03/25 Java/Android
Python+Selenium实现抖音、快手、B站、小红书、微视、百度好看视频、西瓜视频、微信视频号、搜狐视频、一点号、大风号、趣头条等短视频自动发布
2022/04/13 Python