关闭

JavaScript之四:自定义类型

561人阅读 评论(0) 收藏 举报
分类:

四,自定义类

1> 简单模式

var person = new Object ();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function(){
 alert(this.name);
};
person.sayName();

缺陷:

i>声明相同对象,需要大量重复代码

ii>无法记录类别信息。检测出还是Object类型。


2> 工厂模式

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 person = createPerson("Nicholas", 29, "Software Engineer");
person.sayName();

优势:封装了重复代码。

缺陷:仍然无法记录类别信息。检测出还是Object类型。


3> 构造函数模式

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function(){
    alert(this.name);
  };
}
var person = new Person("Nicholas", 29, "Software Engineer");
person.sayName();
优势:可通过instanceof方法,获得类型信息,是Person类型。

Why:因为当使用new关键字调用函数时,JavaScript会做一些额外的事。后面再讲。

缺陷:类的方法,其实也是对象,在调用构造函数时,会被重复实例化,类的实例无法共用方法,造成浪费。


4> 原型模式

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
  alert(this.name);
};
优势:可获得类型信息。用此方法生成的对象,可共享属性和方法。

Why:

当定义函数时,JavaScritp会做一些额外的事,就是为函数添加一个名为prototype的属性,它是一个指针,指向一个新的对象,我们将其叫做原型对象。

当在Person中添加属性和方法时,实际上都添加到了这个新的原型对象中。并且这个新对象会拥有一个constructor的属性,反指向该构造函数。

当使用new调用函数时,实际上,JavaScript会在返回的新对象中,添加一个名为_proto_的属性,指向了该函数的原型对象。

当调用一个对象的属性和方法时,会先查看对象本身是否有该属性和方法,如果有,则调用。如果没有,则会找到该对象的_proto_属性所指的原型对象,查看原型对象是否有要调用属性和方法。依次类推。

(当调用instanceof方法时,会试图从自身查找constructor属性,但没有,就会上溯查找_proto_属性所指的原型对象,如果有constructor属性,则返回,这也是为什么上述构造函数模式可以记录类别信息的原因)

因此,用原型模式定义类,实例化出的对象,会共享属性和方法。

缺陷:虽然可共享,但当有属性是引用型对象时,会造成实例之间同时操作一个引用对象,造成混淆。


5> 构造函数和原型的组合模式

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);
  }
}
优势:由于我们只是想在对象间共享方法,因此,在构造函数的基础上,将方法的定义改用原型模式定义即可。

覆盖:

当调用对象的方法或属性时,实际上就是先搜索自身,如果搜索不到,才会通过_proto_属性到原型对象中搜索。因此,一旦对象也定义了同名的方法或属性,则会覆盖到原型对象中的方法和属性。对象可通过delete操作符,将对象自己的方法和属性删除,取消覆盖。

判断:

有时需要判断一个属性和方法是否是自身的,还是原型对象的。可调用对象的hasOwnProperty(),如果这个属性是对象自身的,则返回true。

而使用in操作符,只要有这个属性,无论从自身来,还是从原型对象来,都回返回true。

因此可结合使用,来判断属性和方法是否来自原型对象 (name in object) && ! object.hasOwnProperty(name)。


6> 动态原型模式

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);
    };
  }
}
优势:封装性

7> 寄生构造函数模式

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;
}
优势:适合对已有类进行功能扩展。

缺陷:无法检测类型。


8>稳妥构造函数模式

function Person(name, age, job){
  var o = new Object();
  o.sayName = function(){
    alert(name);
  }
  return o;
}
优势:可创建稳妥对象,所谓稳妥对象,就是没有公共属性,并且其方法也不引用this的对象。适合安全环境(这些环境禁用this和new)。

缺陷:无法检测类型。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:59659次
    • 积分:815
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:102篇
    • 译文:0篇
    • 评论:0条
    文章分类