title: (犀牛书)
tags: 创建对象,对象直接量,new创建对象 ,原型,Object.create()
创建对象
- 三个方法:通过对象直接量、关键字new、Object.create()函数创建对象
1.1对象直接量
- 什么是对象直接量?
由若干名/值对组成的映射表,名/值对中间由冒号(:)分隔,名/值对之间用逗号(,)分隔,整个映射表用花括号({})括起来 。如:
var student = {
name: 'xiaoming',
age: 12,
isStudent: true
};
其中属性名可以是:标识符 / 字符串直接量(包含空字符串)
属性值可以是: 任意类型的js表达值(表达式的值可以是原始值,也可以是对象值)
var empty = {}; //没有任何属性的对象
var point = {x: 0, y: 0}; //有两个属性的对象
var point = {x: point.x, y: point.y+1}; //一个更复杂的值
var book = {
"main title": "helloJS", //1
"sub-title": "The Definitive Guide", //2
"for": "all audiences", //3
author: {
firstname: "David",
surname: "Flanagan"
}
};
- 注意,上面代码中标注1,2,3 的地方。 属性名分别是用字符串来表示的,为什么?
- "main title" 属性名字里含有空格,必须使用字符串表示
- "sub-title" 属性名字里含有连字符,必须使用字符串
- "for" 属性名字里含有保留字,必须使用字符串
- 对象直接量的特点
对象直接量是一个表达式
这个表达式每次运算都会创建 并初始化 一个 新的对象
每次计算对象直接量的时候,也都会计算它的每个属性值
所以,在一个重复调用函数体中,的循环体内,使用了对象直接量,它将创建很多新对象,并且每一次创建的对象的属性值也有可能不一样。
1.2通过new创建对象
关键字new后跟随一个函数调用(这里的函数成为:构造函数),就可以创建并初始化一个新对象。之后赋值给一个变量(一变以后的调用)。
这里的构造函数用于初始化一个新创建的对象。
js中的原始类型————都包含内置构造函数。如:
var o = new Object(); //创建一个空对象,与{}一样
var a = new Array(); //创建一个空数组,与[]一样
var d = new Date(); //创建一个可以表示当前时间的对象
var r = new RegExp("js") //创建一个可以进行匹配模式的RegExp对象
1.3原型
- 每一个js对象(null除外)都和另一个对象相关联,“另一个”对象就是我们熟知的————原型。每一个对象都从原型继承属性。
- 所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过
Object.prototype
获得对原型对象的引用。
- 通过关键字new和构造函数调用创建的对象的原型就就是——构造函数的
prototype
属性的值。
因此,通过new Object()
创建的对象继承自Object.prototype
,通过new Array()
创建的对象的原型就是Array.prototype
,通过new Date()
创建的对象的原型就是Date.prototype
。
注意:1.
Object.prototype
是一个没有原型的对象,它不继承任何属性。其余的对象都是普通对象,普通对象都具有原型。- 所有的内置构造函数(以及大部分自定义的构造函数)都有一个继承自
Object.prototype
的原型。
- 所有的内置构造函数(以及大部分自定义的构造函数)都有一个继承自
例如:Date.prototype
的属性————继承自————Object.prototype
.
因此由new Date
创建的Date对象的属性,同时继承自————Date.prototype和Object.prototype
1.4 Object.create()
ES5中定义了一个名为——Object.create()
的方法,其作用是:创建一个新对象。
Object.create(proto[, propertiesObject])
这个语法的第一个参数是:新创建对象的原型。第二个参数是可选值,可以对对象的属性进行操作。
通过传入一个原型对象来创建一个新对象,新对象继承自原型的属性和方法。
-
Object.create()
是一个静态函数,不能作为不能作为某个对象的调用方法来使用。只需要传入所需要的原型对象即可。如:
var o = Object.create({name:xiaoming, age:16 }); //o继承了原型的属性name与age
- 那么,如果传入的原型(参数)是:null,会怎么样?
Object.create(null);
??
首席null(空),被创造的新对象,没有任何可继承的方法与属性。如:不能与任何运算符工作。甚至也不包括toString()方法。
var n = Object.create(null); //代码运行返回的结果是:{}。 但是n 不继承任何方法与属性,
-
Object.create(proto)
方法创建一个新对象,会继承自原形的属性与方法,那么如果我们想创建一个普通的空对象,比如:通过对象直接量{}
,或new Object()
这样的方法,应该怎么办?
只需要传入一个
Object.prototype
即可,例如:
var o2 = Object.create(Object.prototype); //创建的新对象与{}和new Object一样。
总结(一个强大的特性):
- 任意的原型都能创造新对象。
- 任意的对象都可以被继承给新对象。
ES3中可以用类似以下的代码来模拟原型继承:
(也是一个对象继承函数的案例)
//inherit()返回一个继承自原型对象P的属性的新对象
//以下代码中Object.create()是ES5的方法,需要验证是否可用。(特性侦查)
//如果不存在Object.create()方法,则退化使用其他方法。
function inherit(p) {
if(p == null) throw TypeError() //如果对象是null,则抛出异常
if(Object.create)
return Object.create(p) //如果存在此方法优先使用
var t = typeof p; //否则进行进一步检查
if(t !== "object" && t !== "function") throw TypeError();
function f(){}; //定义一个空构造函数。
f.prototype = p; //将构造函数f的原型设置为p,函数f就继承自p的属性了
return new f(); //使用f()创建p的继承对象
}
- inherit()与Object.create()的区别
相同点:都是以参数为原型, 返回的新对象继承自原型的属性。
不同点:1. inherit()不能传入null原形来创建对象。 2. inherit()不能接受可选的第二个参数。
- inherit()用作:防止库函数无意间修改那些不受你控制的对象。
因为:inherit()不是将对象直接作为参数传入函数,而是将它的继承对象传入函数。
所以:实际上读取的是继承来的值。如果给继承属性赋值,则这些属性只会影响继承属性自身,而不是原始对象。例:
var o = {x: "don't change this value"}
library_function(inherit(o)); //防止对o的意外修改。