1

==什么是对象?==
就是无序属性的集合,通过属性或者方法名与值的一一映射。
==对象的属性类型==
对象中还定义了一些js中不能直接访问的属性,是为了实现js引擎用的。有数据属性访问器属性两种。
1.数据属性
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有 4 个描述其行为的
特性。

把新值保存在这个位置。这个特性的默认值为 undefined。

要修改属性默认的特性,必须使用 ECMAScript 5 的 Object.defineProperty()方法。

clipboard.png
注意:
1》 configurable 设置为 false,表示不能从对象中删除属性。如果对这个属性调用 delete,则 在非严格模式下什么也不会发生,而在严格模式下会导致错误。而且,一旦把属性定义为不可配置的, 就不能再把它变回可配置。
2》在调用 Object.defineProperty()方法时,如果不指定,configurable、enumerable 和 writable 特性的默认值都是 false。
2.访问器属性
访问器属性不包含数据值;包含一对儿 getter 和 setter 函数(不过,这两个函数都不是必需的)。 在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter 函数并传入新值,这个函数负责决定如何处理数据。访问器属性有如下 4 个特性。

 [[Get]]:在读取属性时调用的函数。默认值为 undefined。
 [[Set]]:在写入属性时调用的函数。默认值为 undefined。
访问器属性不能直接定义,必须使用 Object.defineProperty()来定义。

clipboard.png

可以通过Object.definePro- perties()定义多个属性;
使用 ECMAScript 5 的 Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。

==创建对象的方式==
通过字面量的方式可以创建对象,但是创建有类似属性的对象时会产生大量重复代码。
1.工厂模式
用函数来封装以特定接口创建对象。

clipboard.png
缺点就是无法知道一个对象的类型。
2.构造函数模式

clipboard.png
通过构造函数创建的对象可以通过constructor标识对象类型,通过instanceof检测对象类型。
构造函数模式与工厂模式对比:
1》没有显式地创建对象;
2》直接将属性和方法赋给了 this 对象;
3》 没有 return 语句。
通过new操作符调用构造函数会经历4个步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。

clipboard.png
构造函数也可作为普通函数调用
Person("Greg", 27, "Doctor"); // 添加到window window.sayName(); //"Greg"
也可以在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Kristen", 25, "Nurse"); o.sayName(); //"Kristen"

构造函数模式的缺点就是每个方法都要在每个实例上重新创建一遍

function Person(name, age, job){

    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = new Function("alert(this.name)"); 
    // 与声明函数在逻辑上是等价的 

}
alert(person1.sayName == person2.sayName); //false
3.原型模式

clipboard.png
通过prototype为对象添加属性和方法。这样实例就能共享原型的属性和方法。
1》原型具有动态性。在实例化后定义的原型方法,实例也能调用。

clipboard.png

2》原型的简单写法。

clipboard.png

可以将原型简写如上,但是这种写法实际上是重新写了原型,新原型的constructor已经改变,指向object。所以可以重新设置constructor。
而且如果在实例化后重写原型,则已经实例的对象依旧访问原来原型对象,不能访问新原型的方法和属性。

clipboard.png

组合使用构造函数模式和原型模式

clipboard.png

===继承===

继承:利用原型让一个引用类型继承另一个引用类型的属性和方法。

1.原型链继承

包含引用类型值的原型属性会被所有实例共享;而 这也正是为什么要在构造函数中,而不是在原型对象中定义属性的原因。在通过原型来实现继承时,原型实际上会变成另一个类型的实例。于是,原先的实例属性也就顺理成章地变成了现在的原型属性了。
原型链的问题是:由于原型中包含引用类型值所带来的问题。和在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上,应该说是没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。实践中很少会单独使用原型链。

2.构造函数继承

借用构造函数:别忘了,函数只不过是在特定环境中执行代码的对象, 因此通过使用 apply()和 call()方法也可以在(将来)新创建的对象上执行构造函数。

clipboard.png

借用构造函数的问题
如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定 义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结 果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

组合继承

clipboard.png

组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继 承模式。


搁浅
693 声望323 粉丝

想进BAT的前端er