美文网首页
第六章 面向对象的程序设计

第六章 面向对象的程序设计

作者: dudu_du | 来源:发表于2017-06-16 20:26 被阅读0次
  • 我们可以ECMAScript的对象想象成散列表:无非就是一组名值对,其中值是数据或函数。
  • 每个对象都是基于一个引用类型创建的,这个引用类型可以使第五章讨论的原生类型,也可以是开发人员定义的类型。

6.1 理解对象

对象字面量方法

6.1.1 属性类型

ECMAScript中有两种属性:数据属性和访问器属性。

6.2 创建对象

使用一个同一个接口创建很多对象,会产生大量的重复代码。

6.2.1 工厂模式

<pre>
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("zhang",22,"software engineer");
</pre>

工厂模式虽然解决了创建多个对象的问题,但是没有解决对象识别的问题(即怎样知道一个对象的类型)。

6.2.2 构造函数模式

<pre>
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
}
}
var person1 = new Person("zhang",22,"doctor");
</pre>

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

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

构造函数模式和工厂模式差别:

  • 没有显示创建对象
  • 直接将属性和方法赋给了this对象
  • 没有return语句

构造函数的主要问题,就是每个方法都要在每个实例上重新创建一次。ECMAScript中的函数是对象,因此每定义一个函数,也就是实例化一个对象,不同实例上的同名函数是不相等的。
<pre>
function Person(){
this.sayName = new Function("alert(this.name)"j);//与声明函数在逻辑上是等价的
}
alert(person1.sayName == person2.sayName);//false
</pre>

6.2.3 原型模式

每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含由特定类型的所有实例共享的属性和方法。

<pre>
function Person(){

}

Person.prototype.name = "zhang";
Person.prototype.age = 22;
Person.prototype.job = "doctor";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.name = "jian";
person1.sayName();//jian

var person2 = new Person();
person2.sayName();//zhang
</pre>

1497614688(1).jpg

hasOwnProperty()方法可以检测一个属性是存在与实例中还是存在与原型中。这个方法(不要忘记他是从Object继承来的)只在给定属性存在于对象实例中时,才会返回true。

<pre>
function Person(){

}

Person.prototype.name = "zhang";
Person.prototype.age = 22;
Person.prototype.job = "doctor";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.name = "jian";
person1.sayName();

var person2 = new Person();
person2.sayName();
function Person(){

}

Person.prototype.name = "zhang";
Person.prototype.age = 22;
Person.prototype.job = "doctor";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.name = "jian";
person1.sayName();

var person2 = new Person();
person2.sayName();
</pre>

通过使用 hasOwnProperty() 方法,什么时候访问的是实例属性,什么时候访问的是原型属性就一清二楚了。调用 person1.hasOwnProperty( "name") 时,只有当 person1 重写 name 属性后才会返回 true ,因为只有这时候 name 才是一个实例属性,而非原型属性。图 6-2 展示了上面例子在不同情况下的实现与原型的关系(为了简单起见,图中省略了与 Person 构造函数的关系)。

image.png

for-in方法
<pre>
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();
var person2 = new Person();
alert(person1.hasOwnProperty("name")); //false
alert("name" in person1); //true
person1.name = "Greg";
alert(person1.name); //"Greg" ——来自实例
alert(person1.hasOwnProperty("name")); //true
alert("name" in person1); //true
alert(person2.name); //"Nicholas" ——来自原型
alert(person2.hasOwnProperty("name")); //false
alert("name" in person2); //true
delete person1.name;
alert(person1.name); //"Nicholas" ——来自原型
alert(person1.hasOwnProperty("name")); //false
alert("name" in person1); //true
</pre>

调用 "name" in person1 始终都返回 true ,无论该属性存在于实例中还是存在于原型中。同时使用 hasOwnProperty() 方法和 in 操作符,就可以确定该属性到底是存在于对象中,还是存在于原型中,如下所示。

<pre>
function hasPrototypeProperty(object, name){
return !object.hasOwnProperty(name) && (name in object);
}
</pre>

更简单的原型语法

<pre>
function Person(){
}
Person.prototype = {
name:"zhang",
sayName:function(){
alert(this.name);
}
}
</pre>

在上面的代码中,我们将 Person.prototype 设置为等于一个以对象字面量形式创建的新对象。最终结果相同,但有一个例外: constructor 属性不再指向 Person 了。前面曾经介绍过,每创建一个函数,就会同时创建它的 prototype 对象,这个对象也会自动获得 constructor 属性。而我们在这里使用的语法,本质上完全重写了默认的 prototype 对象,因此constructor 属性也就变成了新对象的 constructor 属性(指向 Object 构造函数),不再指向 Person 函数。此时,尽管 instanceof操作符还能返回正确的结果,但通过 constructor 已经无法确定对象的类型了,如下所示。
<pre>
var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(friend.constructor == Object); //true
</pre>

如果constructor很重要,可以如下代码设置:
<pre>
function Person(){
}
Person.prototype = {
constructor : Person,
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};
</pre>

相关文章

  • prototype (原型) 属性

    这篇文章是基于 <>第六章面向对象的程序设计 6.2.3原型模式 我们每创建...

  • JavaScript高级程序设计(第3版) 笔记

    第六章 面向对象的程序设计 6.1 理解对象 6.1.1 属性类型 ECMAScript 中有两种属性: 数据属性...

  • javascript高级程序设计(第6章)-- 面向对象的程序设

    第六章:面向对象的程序设计 本章内容: 理解对象属性 理解并创建对象 理解继承 ECMA-262把对象定义为:"无...

  • 《软件工程》笔记7

    面向对象的实现 面向对象的程序设计最好还是选用面向对象的编程语言。 良好的程序设计风格对于面向对象实现来说格外重要...

  • 第四章 对象与类

    1 面向对象程序设计概述 面向对象程序设计(简称OOP)是当今主流的程序设计范型 Java是完全面向对象的,必须熟...

  • 《Java核心技术卷 I》之 Java对象与类

    Java对象与类 面向对象程序设计 面向对象程序设计,简称OOP,Java语言就是完全面向对象的。 类 类(cla...

  • JavaScript面向对象编程指南--读书笔记(上)

    第一章:面向对象的JavaScript 面向对象的程序设计 面向对象程序设计(oop)中最常用到的概念: 对象、方...

  • python面向对象编程

    面向对象编程(一) 1、面向过程程序设计与面向对象程序设计: 面向过程的程序设计把计算机程序视为一系列的命令集合,...

  • oc编程思想

    面向对象概念 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一...

  • 编程语言基础概念1

    什么是面向对象? 面向对象:指在程序设计中采用封装、继承、多态等设计方法。 什么是面向过程? 面向过程:程序设计按...

网友评论

      本文标题:第六章 面向对象的程序设计

      本文链接:https://www.haomeiwen.com/subject/rvpmqxtx.html