UDN-企业互联网技术人气社区

板块导航

浏览  : 1250
回复  : 0

[讨论交流] JavaScript -- 面向对象

[复制链接]
呵呵燕的头像 楼主
发表于 2016-11-27 21:38:21 | 显示全部楼层 |阅读模式
  创建对象

  创建定义对象的最简单方式就是创建一个 Object 实例,然后为其添加属性和方法。

  1.   var person = new Object();

  2.   person.name = "Hwaphon";

  3.   person.age = 19;

  4.   person.sayName = function() {

  5.   console.log(this.name);

  6.   }
复制代码


  当然,我们还可以通过一个对象字面量创建对象,事实上这种方式也是使用最多的。

 
  1.  var person = {

  2.   name: "Hwaphon",

  3.   age: 19,

  4.   sayName: function() {

  5.   console.log(this.name);

  6.   }

  7.   };
复制代码


  虽然 Object 构造函数或对象字面量都可以创建单个对象,但是这两种方式存在明显的缺点: 使用同一接口创建很多对象,会产生大量重复的代码。为了解决这个问题,人们开始用工厂模式的一种变体。下面就用类工厂模式解决这种问题。

  1.   function createPerson(name, age) {

  2.   var o = new Object();

  3.   o.name = name;

  4.   o.age = age;

  5.   o.sayName = function() {

  6.   console.log(this.name);

  7.   };

  8.   return o;

  9.   }
复制代码


  可以频繁的调用上面这个函数以创造不同的对象,但是这种方法仍然存在一个问题,就是对象识别问题,即我们无法判断创建出来的对象是 Person, 我们能判断的就是它属于 Object 类型而已。所以这个时候又出现了一种创建对象的方式,就是构造函数模式。

  1.   function Person(name, age) {

  2.   this.name = name;

  3.   this.age = age;

  4.   this.sayName = function() {

  5.   console.log(this.name);

  6.   }

  7.   }

  8.   var person = new Person("Hwaphon", 21);

  9.   person.sayName();
复制代码


  这个时候我们就可以利用 instanceof 运算符检测我们创建的对象类型。

  1.   console.log(person instanceof Object); // true

  2.   console.log(person instanceof Person); // true
复制代码


  我们通过 new 操作符去创建一个对象,这也就意味着每个对象是相互独立的,当然也包括 sayName 方法, 但是这个方法在每个实例中实现的功能是相同的,实在没必要每创建一个对象实例就创建一个 Function 实例。我们通过以下代码可以看出这种问题。

 
  1.  var person1 = new Person("Hwaphon", 21);

  2.   var person2 = new Person("Hello", 22);

  3.   console.log(person1.sayName == person2.sayName); // false
复制代码


  如果是这样的话,我们只能将函数放置到构造函数外去解决这个问题。

  1.   function Person(name, age) {

  2.   this.name = name;

  3.   this.age = age;

  4.   this.sayName = sayName;

  5.   }

  6.   function sayName() {

  7.   console.log(this.name);

  8.   }

  9.   var person1 = new Person("Hwaphon", 21);

  10.   person1.sayName();
复制代码


  虽说这种方法能解决上述问题,但是又引入了新的问题,因为这种方式引入了全局的 sayName 函数。更让人无法接受的是,如果对象需要定义很多方法,那么就要定义多个全局函数,这样我们自定义的引用类型就丝毫没有封装性可言了。所以不得不引入原型模式来解决这个问题。

  原型模式

  我们创建的每个函数都有一个 prototype 属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型的好处是可以让所有的对象实例共享它保函的属性和方法。所以为了解决上面的问题,我们可以像下面这样定义。

 
  1.  function Person(name, age) {

  2.   this.name = name;

  3.   this.age = age;

  4.   }

  5.   Person.prototype.sayName = function() {

  6.   console.log(this.name);

  7.   }

  8.   console.log(person1.sayName == person2.sayName); // true
复制代码


  通过 hasOwnProperty() 方法可以检测实例属性,而非原型属性,通过 in 不仅可以检测实例属性也可以检测原型属性。

  1.   function Person(name, age) {

  2.   this.name = name;

  3.   this.age = age;

  4.   }

  5.   Person.prototype.sayName = function() {

  6.   console.log(this.name);

  7.   }

  8.   var person = new Person("Hwaphon", 21);

  9.   if (person.hasOwnProperty("sayName")) {

  10.   console.log("true");

  11.   }

  12.   if ("sayName" in person) {

  13.   console.log("true");

  14.   }
复制代码


  当然,如果你想在原型添加多个函数,那么可以将这些方法组成一个对象字面量。

  1.   function Person(name, age) {

  2.   this.name = name;

  3.   this.age = age;

  4.   }

  5.   Person.prototype = {

  6.   sayName: function() {

  7.   console.log(this.name);

  8.   },

  9.   sayAge: function() {

  10.   console.log(this.age);

  11.   }

  12.   };
复制代码


  这个时候存在一个问题,因为这个时候 constructor 不再指向 Person 了,所以我们可以手动设置 constructor。

  1.   Person.prototype = {

  2.   constructor: Person,

  3.   sayName: function() {

  4.   console.log(this.name);

  5.   },

  6.   sayAge: function() {

  7.   console.log(this.age);

  8.   }

  9.   };
复制代码


  上面我们将原型和构造函数分开了,这可能会让人感到困惑,所以可以使用动态原型模式,将所有信息封装在构造函数中。

  1.   function Person(name, age) {

  2.   this.name = name;

  3.   this.age = age;

  4.   if (typeof this.sayName != "function") {

  5.   Person.prototype.sayName = function() {

  6.   console.log(this.name);

  7.   };

  8.   }

  9.   }

  10.   var person = new Person("Hwaphon", 21);

  11.   person.sayName();
复制代码


  只有在 sayName() 方法不存在的情况下才会将它添加进原型中,所以 if 判断语句只有在初次调用构造函数时才会执行。

  还有一个称为稳妥构造方式的创建方法,当你不想共享任何变量而且环境不允许使用 this, new 的情况下,可以选择这种方式。

  1.   function Person(name, age) {

  2.   var o = new Object();

  3.   o.sayName = function() {

  4.   console.log(name);

  5.   };

  6.   o.sayAge = function() {

  7.   console.log(age);

  8.   };

  9.   return o;

  10.   }

  11.   var person = Person("Hwaphon", 33);

  12.   person.sayName();

  13.   person.sayAge();
复制代码


原文作者:高华峰 来源:开发者头条

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部