学习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 无符号右移运算符
Apr 17 Javascript
Javascript 面向对象(二)封装代码
May 23 Javascript
GRID拖拽行的实例代码
Jul 18 Javascript
EasyUI实现第二层弹出框的方法
Mar 01 Javascript
jquery中toggle函数交替使用问题
Jun 22 Javascript
超赞的动手创建JavaScript框架的详细教程
Jun 30 Javascript
文字垂直滚动之javascript代码
Jul 29 Javascript
JavaScript快速切换繁体中文和简体中文的方法及网站支持简繁体切换的绝招
Mar 07 Javascript
JavaScript常用字符串与数组扩展函数小结
Apr 24 Javascript
JS代码随机生成姓名、手机号、身份证号、银行卡号
Apr 27 Javascript
适合后台管理系统开发的12个前端框架(小结)
Jun 29 Javascript
vue判断按钮是否可以点击
Apr 09 Vue.js
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 分页类 扩展代码
2009/06/11 PHP
PHP5.5在windows安装使用memcached服务端的方法
2014/04/16 PHP
PHP基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
PHP实现中国公民身份证号码有效性验证示例代码
2017/05/03 PHP
PHP封装的分页类与简单用法示例
2019/02/25 PHP
JavaScript 对象的属性和方法4种不同的类型
2010/03/19 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
2014/07/18 Javascript
一个css与js结合的下拉菜单支持主流浏览器
2014/10/08 Javascript
chrome不支持form.submit的解决方案
2015/04/28 Javascript
解析Node.js异常处理中domain模块的使用方法
2016/02/16 Javascript
详解Vue使用 vue-cli 搭建项目
2017/04/20 Javascript
Angular.js中控制器之间的传值详解
2017/04/24 Javascript
JavaScript 值类型和引用类型的初次研究(推荐)
2017/07/19 Javascript
Node实战之不同环境下配置文件使用教程
2018/01/02 Javascript
浅谈ElementUI中switch回调函数change的参数问题
2018/08/24 Javascript
node.js实现为PDF添加水印的示例代码
2018/12/05 Javascript
微信小程序websocket聊天室的实现示例代码
2019/02/12 Javascript
微信小程序整个页面的自动适应布局的实现
2020/07/12 Javascript
vue 在methods中调用mounted的实现操作
2020/08/07 Javascript
Python实现批量检测HTTP服务的状态
2016/10/27 Python
Python求离散序列导数的示例
2019/07/10 Python
浅谈Python中的模块
2020/06/10 Python
python爬虫用mongodb的理由
2020/07/28 Python
Python根据URL地址下载文件并保存至对应目录的实现
2020/11/15 Python
解决pycharm不能自动保存在远程linux中的问题
2021/02/06 Python
毕业生的自我鉴定
2013/10/29 职场文书
新闻学专业应届生求职信
2013/11/08 职场文书
前台文员个人求职信范文
2014/01/05 职场文书
旺仔牛奶广告词
2014/03/20 职场文书
五四青年节演讲稿
2014/05/26 职场文书
优秀班主任经验交流材料
2014/06/02 职场文书
实验室的标语
2014/06/20 职场文书
乡镇爱国卫生月活动总结
2014/06/25 职场文书
终止劳动合同通知书
2015/04/16 职场文书
《攀登者》:“海拔8000米以上,你不能指望任何人”
2019/11/25 职场文书
MATLAB 全景图切割及盒图显示的实现步骤
2021/05/14 Python