学习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 textarea的长度进行验证
May 06 Javascript
js 巧妙去除数组中的重复项
Jan 25 Javascript
jquery 锁定弹出层实现代码
Feb 23 Javascript
非常棒的10款jQuery 幻灯片插件
Jun 14 Javascript
JS实现生成会变大变小的圆环实例
Aug 05 Javascript
javascript实现列表切换效果
May 02 Javascript
从重置input file标签中看jQuery的 .val() 和 .attr(“value”) 区别
Jun 12 Javascript
BootStrap 智能表单实战系列(二)BootStrap支持的类型简介
Jun 13 Javascript
深入理解requestAnimationFrame的动画循环
Sep 20 Javascript
JS使用对象的defineProperty进行变量监控操作示例
Feb 02 Javascript
详解如何搭建mpvue框架搭配vant组件库的小程序项目
May 16 Javascript
Vue 2.0双向绑定原理的实现方法
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
图书管理程序(三)
2006/10/09 PHP
php 图像函数大举例(非原创)
2009/06/20 PHP
php中使用array_filter()函数过滤空数组的实现代码
2014/08/19 PHP
Laravel中10个有用的用法小结
2019/05/06 PHP
Jquery中删除元素的实现代码
2011/12/29 Javascript
Ajax与服务器(JSON)通信实例代码
2016/11/05 Javascript
Bootstrap Table使用整理(一)
2017/06/09 Javascript
vue项目中使用axios上传图片等文件操作
2017/11/02 Javascript
在vue项目中集成graphql(vue-ApolloClient)
2018/09/08 Javascript
如何让微信小程序页面之间的通信不再变困难
2019/06/03 Javascript
vue组件命名和props命名代码详解
2019/09/01 Javascript
改变layer confirm弹窗按钮的颜色方法
2019/09/12 Javascript
Vue项目环境搭建详细总结
2019/09/26 Javascript
简单了解JavaScript sort方法
2019/11/25 Javascript
微信小程序动态添加和删除组件的现实
2020/02/28 Javascript
Python3里的super()和__class__使用介绍
2015/04/23 Python
python 读写txt文件 json文件的实现方法
2016/10/22 Python
Python单例模式的两种实现方法
2017/08/14 Python
Python排序搜索基本算法之希尔排序实例分析
2017/12/09 Python
Python验证文件是否可读写代码分享
2017/12/11 Python
numpy linalg模块的具体使用方法
2019/05/26 Python
python自动化测试无法启动谷歌浏览器问题
2019/10/10 Python
python集成开发环境配置(pycharm)
2020/02/14 Python
Pytorch mask_select 函数的用法详解
2020/02/18 Python
Python如何使用input函数获取输入
2020/08/06 Python
CSS3实现多样的边框效果
2018/05/04 HTML / CSS
ECCO爱步美国官网:来自丹麦的鞋履品牌
2016/11/23 全球购物
小米旗下精品生活电商平台:小米有品
2018/12/18 全球购物
瑞典度假品牌:OAS
2019/05/28 全球购物
日本最大化妆品和美容产品的综合口碑网站:cosme shopping
2019/08/28 全球购物
沃尔玛加拿大:Walmart.ca
2020/03/02 全球购物
城建学院毕业生自荐信
2014/01/31 职场文书
年度考核表个人总结
2015/03/06 职场文书
上课迟到检讨书范文
2015/05/06 职场文书
2015年度残疾人工作总结
2015/05/14 职场文书
Python内置的数据类型及使用方法
2022/04/13 Python