创建对象

第一种:基于Object对象

var person = new Object();
person.name = 'My Name';
person.age = 18;
person.getName = function(){
return this.name;
}

第二种:对象字面量方式(比较清楚的查找对象包含的属性及方法)

var person = {
name : 'My name',
age : 18,
getName : function(){
return this.name;
}
}

使用Object构造函数或对象字面量都可以创建对象,但缺点是创建多个对象时,会产生大量的重复代码,因此下面介绍可解决这个问题的创建对象的方法

1、工厂模式

function createPerson(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.getAge = function () {
return this.age;
};
return o;
}
var person = createPerson('张三', 23);  
console.log(person.name);  //'张三'
console.log(person.age);    //23
console.log(person.getAge());  //23

缺点:创建对象交给一个工厂方法来实现,可以传递参数,但主要缺点是无法识别对象类型,因为创建对象都是使用Object的原生构造函数来完成的。

2、构造函数模式

function Person(name, age) {
this.name = name;
this.age = age;
this.getAge = function () {
return this.age;
};
}
var person = new Person('张三', 23);
console.log(person.name);  //'张三'
console.log(person.age);   //23
console.log(person.getAge());  //23
alert(person instanceof Person);  //true;
alert(person instanceof Object);  //true;
 

2.1 使用自定义的构造函数(与普通函数一样,只是用它来创建对象),定义对象类型(如:Person)的属性和方法。它与工厂方法区别在于:

  • 没有显式地创建对象
  • 直接将属性和方法赋值给this对象;
  • 没有return语句;

此外,要创建Person的实例,必须使用new关键字,以Person函数为构造函数,传递参数完成对象创建;

2.2 要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:

(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。

在前面例子的最后, person1 和 person2 分别保存着 Person 的一个不同的实例。这两个对象都有一个 constructor (构造函数)属性,该属性指向 Person ,如下所示。
alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true

对象的 constructor 属性最初是用来标识对象类型的。

创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。

function Person(name, age) {
this.name = name;
this.age = age;
this.getAge = new Function ("return this.age");  //和上面是一样的,会重复创建多个函数
}

缺点:上述代码,创建多个实例时,会重复调用new Function();创建多个函数实例,这些函数实例还不是一个作用域中,当然这一般不会有错,但这会造成内存浪费。

3、原型模式

function Person(name) {
this.name = name;
}
Person.prototype.age = 23;
Person.prototype.getAge = function () {
return this.age;
};
var person = new Person('张三');
console.log(person.name);  //'张三'
console.log(person.age);  //23
console.log(person.getAge());  //23

JS每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,它是所有通过new操作符使用函数创建的实例的原型对象。

原型对象最大特点是,所有对象实例共享它所包含的属性和方法,也就是说,所有在原型对象中创建的属性或方法都直接被所有对象实例共享。

实例属性或方法的访问过程是一次搜索过程:

  • 首先从对象实例本身开始,如果找到属性就直接返回该属性值;
  • 如果实例本身不存在要查找属性,就继续搜索指针指向的原型对象,在其中查找给定名字的属性,如果有就返回;

基于以上分析,原型模式创建的对象实例,其属性是共享原型对象的;但也可以自己实例中再进行定义,在查找时,就不从原型对象获取,而是根据搜索原则,得到本实例的返回;简单来说,就是实例中属性会屏蔽原型对象中的属性;

可以通过使用hasOwnProperty()方法来判断,属性是实例本身的,还是原型上的。

person.hasOwnProperty("name");    //true
person.hasOwnProperty("age"); //false

缺点:最主要是当对象的属性是引用类型时,它的值是不变的,总是引用同一个外部对象,所有实例对该对象任何一个地方产生的改动会引起其他实例的变化。

function Person(name) {
this.name = name;
}
Person.prototype.age = 23;
Person.prototype.color = ['red', 'yellow'];
var person1 = new Person('张三');
console.log(person1.name);  //'张三'
console.log(person1.color);  //["red", "yellow"]
person1.color.push('black');  
var person2 = new Person('李四');
console.log(person2.name);  //'李四'
console.log(person2.color);  //["red", "yellow", "black"]  //person1的修改影响了person2

4、组合使用构造函数模式及原型模式

目前最为常用的定义类型方式,是组合使用构造函数模式与原型模式。

构造函数模式用于定义实例的属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方方法的引用,最大限度的节约内存。

此外,组合模式还支持向构造函数传递参数,可谓是集两家之所长。

function Person(name, age) {
this.name = name;
this.age = age;
this.color = ['red', 'yellow'];
}
Person.prototype = {
constructor : Person,  //原型字面量形式会将对象的constructor变Object,此外强制指回Person;
getAge : function () {
return this.age;
}
};
var person1 = new Person('张三', 23);
person1.color.push('black');
console.log(person1.name);  //张三
console.log(person1.color);  //["red", "yellow", "black"]
console.log(person1.getAge());  //23
var person2 = new Person('李四', 24);
console.log(person2.name);  //李四
console.log(person2.color);  //['red','yellow']  
console.log(person2.getAge());  //24

5、动态原型模式

组合模式中实例属性与共享方法(由原型定义)是分离的,这与纯面向对象语言不太一致;动态原型模式将所有构造信息都封装在构造函数中,又保持了组合的优点。其原理就是通过判断构造函数的原型中是否已经定义了共享的方法或属性,如果没有则定义,否则不再执行定义过程。该方式只原型上方法或属性只定义一次,且将所有构造过程都封装在构造函数中,对原型所做的修改能立即体现所有实例中:

function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
if (typeof this.getName != 'function') {//通过判断实例封装
  Person.prototype = {
    constructor: Person,//原型字面量方式会将对象的constructor变为Object,此外强制指回Person
    getName: function () {
      return this.name;
    }
  }
}
var person1 = new Person('Jack', 19, 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', 39, 'Mechanical Engneer');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法

javascript 面向对象(多种创建对象的方式)的更多相关文章

  1. js面向对象 多种创建对象方法小结

    转自js面向对象 多种创建对象方法小结 1.对象字面量 var clock={ hour:12, minute:10, second:10, showTime:function(){ alert(th ...

  2. Javascript面向对象之创建对象

    面向对象的语言具有一个共同的标志,那就是具有“类”的概念,但是在javascript中没有类的概念,在js中将对象定义为“无序属性的集合,其属性可以包含基本值,对象或者函数”,即其将对象看作是一组名值 ...

  3. javascript三种创建对象的方式

    javascript是一种“基于prototype的面向对象语言“,与java有非常大的区别,无法通过类来创建对象.那么,既然是面象对象的,如何来创建对象呢? 一.通过”字面量“方式创建. 方法:将成 ...

  4. JavaScript面向对象实现

    JavaScript面向对象实现 一:面向对象三大特征 继承,封装,多态! 二:JavaScript自定义对象  创建对象的方式: 方式1,对象初始化器方式: <script type=&quo ...

  5. 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)

    这一次我们深入的学习一下JavaScript面向对象技术,在学习之前,必要的说明一下一些面向对象的一些术语. 这也是全部面对对象语言所拥有的共同点.有这样几个面向对象术语: 对象 ECMA-262把对 ...

  6. JavaScript 常见创建对象的方式

    JavaScript 有哪几种创建对象的方式? javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON:但写法有很多种,也能混合使用. (1)对象字面量的方式 ...

  7. javascript中创建对象的方式总结

    javascript中创建对象的方式总结 具体代码如下: //创建对象的方式: //创建方式一 var person=new Object(); person.name='jack'; person. ...

  8. JavaScript高级特性-创建对象的九种方式

    1. 对象字面量 通过这种方式创建对象极为简单,将属性名用引号括起来,再将属性名和属性值之间以冒号分隔,各属性名值对之后用逗号隔开,最后一个属性不用逗号隔开,所有的属性名值对用大括号括起来,像这样: ...

  9. Javascript面向对象——创建对象、构造函数的原型

    Javascript面向对象--创建对象.构造函数的原型 其实:JavaScript中的创建类,就是创建一个构造函数,在创建对象时用到new这个关键字, 一.创建对象 1.函数创建对象 functio ...

随机推荐

  1. Python中几种数据类型list, tuple,dict,set的使用演示

    还是直接上代码,看着代码运行,看函数介绍 # coding=utf-8 # 1 list-列表 的用法 students = [1,2,3] a = 5 classmates = [students* ...

  2. Oracle数据库创建用户小结

    前言:使用Oracle开发系统过程中,会涉及到数据库用户的建立,及给该用户分配权限.刚开始接触开发的时候,对这些操作是一种茫茫然的状态.后,经过积累,对这方面有了一定的认识,现总结一些,一则,巩固自身 ...

  3. 常用API

    1 System类 System类包含一些有用的类和字段.它不能被实例化. 属性和方法都是静态的. 1.1 常见方法 返回以毫秒为单位的当前时间 public static long currentT ...

  4. python3中time模块的用法及说明

    python中,导入time模块使用的命令是 import time 可以使用以下命令查看time模块内置的能够使用的方法: dir(time) 可以使用以下命令查看time模块中每个内置方法的说明: ...

  5. python小白之路

    阅读目录: 第一章:计算机基础 计算机硬件.操作系统.网络协议 第二章:python基础 初识python.常量变量.输入输出运算符.条件与循环语句.数字与字符串.列表与字典.元组与集合.阶段小测.字 ...

  6. 【AIX】AIX内存机制

    [AIX]AIX内存机制 1  虚拟内存 虚拟内存是物理内存和交换空间(Paging Space)组合形成的虚拟内存空间, 通过虚拟的地址空间映射到物理内存或者 Paging Space. 在 AIX ...

  7. ZOJ1450 BZOJ1136 BZOJ1137 HDU3932[最小圆覆盖]

    Minimal Circle Time Limit: 5 Seconds      Memory Limit: 32768 KB You are to write a program to find ...

  8. testlink用例的导出到Excel

    一直在网上寻找怎么把testlink的用例导出到Excel中,以及把Excel中已经写好的用例导入到Testlink中的方法.根据现网的经验,然后修改了一下.贴出来,以飨有这方面需求的测试同仁. Te ...

  9. 第一周 动态规划Dynamic Programming(一)

    一.概念 动态规划是运筹学的一个分支,是求解决策过程最优化的数学方法.动态规划是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决. 1.试用情况: 2.解决步骤 ...

  10. js中sum(2,3,4)和sum(2)(3)(4)都返回9并要求扩展性

    网上有很多关于sum(1)(2)(3),sum(1,2,3)之类的面试题要求输出相同的结果6并要求可以满足扩展,即有多个参数时也能符合题设的要求,所以自己写了部分例子可以大概满足这些面试题的要求 &l ...