此文是《Javascript Elightment》的读书笔记,希望和有意向从jS库的使用者转变成js的开发者的童鞋们一起分享。
第一篇 javascript 对象
创建对象
Js中,所有事物都是对象或者可以表现得像对象。
记住:对象事实上就是一个属性(名字和对应的值)的容器。
方法其实也是对象的一个属性,它包含了用来操作对象的function()对象。如果没有方法,对象除了保存静态属性外什么也做不了。
创建一个对象:var myObject = new Object();
上面代码解析: 我们用一个指向Object() 构造函数的空对象去创建新对象。
可以把构造函数看成生产预定义好的对象的模板。
我们也可以自己创建一个对象构造函数,用来大量“生产”我们需要的对象。
如:
var Person = function(living, age, gender) {
this.living = living;
this.age = age;
this.gender = gender;
this.getGender = function() {return this.gender;};
};
var cody = new Person(true, 33, 'male');
js 构造函数构建和返回对象实例
构造函数的作用是创建一批共享特定属性和方法的对象。
构造函数在正常时候不外乎是一个函数,但是当被new调用后,这个函数就被特殊对待,因为它要设置正准备创建的对象的属性值,然后返回一个建好的对象,这个对象就被认作这个构造函数构造出来的实例。
Js 原生/内置对象(Native/Built-In Object)的构造函数
Js的9个原生对象:
• Number()
• String()
• Boolean()
• Object()
• Array()
• Function()
• Date()
• RegExp()
• Error()
自定义构造函数
自定义的构造函数名字的首字母最好大写。
在创建对象的时候可以省去new关键字,但是在定义构造函数的时候必须明确地返回一个对象。
如:
var myFunction = function(){return {prop: val}};
上面的做法避免了prototype的继承。
用new实例化构造函数
new操作就是告诉js解释器——我们要建一个相应的构造函数的实例。
Math()
Math与其它内置构造函数不一样,它是一个静态对象,并不是构造函数,所以不能用new来构建一个实例,但是你可以用它已经建好的实例(如 Math.PI)。事实上Math只是js用来存储math方法的一个对象。
注意: Math 是一个静态对象(一个包含其它方法的容器),不可以用new操作。
用构造函数创建速记/字面值(Shorthand/Literal Values)
Js提供了“字面值”的快捷方式去制造大多数的内置对象值,所以我们不需要每次都用new操作。
大多数情况字面值方式和new操作做的事是一样的,除了Number(),String()和Boolean().
如:
var myObject = new Object();
var myObjectLiteral = {};
var myNumber = new Number(23);
var myNumberLiteral = 23;
注意: 用字面值创建string, number, boolean对象,刚开始并不是创建一个真正的复杂的对象,而是单纯的一个原始数据类型,只有当这个对象被当做对象用(调用构造函数内的方法,获取属性)时,js才会为这个字面值创建一个封装对象,允许这个字面值像对象一样操作,当构造函数内的方法调用完后,js就会抛弃这个对象,字面值又恢复成单纯的数据类型。(这里解释了为什么“js里所有的事物都是对象或可以像对象一样操作”)。
原始值(Primitive Values) null,undefined,“string”,10,true,false都不是对象
原始值不是对象,它们只是用来表示简单的值。
原始值如何在js中储存和复制
原始值的储存和操作仅限于数值表面的,不可还原的。
var myString = 'foo' // create a primitive string object
var myStringCopy = myString; // copy its value into a new variable
var myString = null; // manipulate the value stored in the myString variable
/* The original value from myString was copied to myStringCopy. This is confirmed
by updating the value of myString then checking the value of myStringCopy */
console.log(myString, myStringCopy); // logs 'null foo'
原始值的对比
如果不是通过new创建的对象,那么原始值的类型还是原始类型。如果用new创建对象,即使数值相同,但是类型已经不再是原始类型了,而变成了对象。
var price1 = 10;
var price2 = 10;
var price3 = new Number('10'); // a complex numeric object because new was used
var price4 = price3;
console.log(price1 === price2); // logs true
/* logs false because price3 contains a complex number object and price 1 is
a primitive value */
console.log(price1 === price3);
// logs true because complex values are equal by reference, not value
console.log(price4 === price3);
// what if we update the price4 variable to contain a primitive value?
price4 = 10;
console.log(price4 === price3); /* logs false: price4 is now primitive
rather than complex */
复合值(Complex Values)
内置对象 Object(),Array(),Function(),Date(),Error(),RegExp()都是复合值,因为它们包含一个或多个原始值和复合值。
复合值在js中如何存储和复制
新创建一个对象后,这个对象会被储存在内存的某个地址里;当你调用这个对象时,你用对象的名字去获得内存地址里的值。
对象的复制并不是像原始值一样单纯在数值表面的复制,复制的是对象的引用值/地址值,并不是真的数值,这意味着对象并不是完全被复制。所以,复制的对象和源对象其实指向同一个地址值,即它们操作的是同一个对象。
var myObject = {};
var copyOfMyObject = myObject; /* not copied by value,
just the reference is copied */
myObject.foo = 'bar'; // manipulate the value stored in myObject
/* Now if we log myObject and copyOfMyObject, they will have a foo property
because they reference the same object. */
console.log(myObject, copyOfMyObject); /* logs 'Object { foo="bar"}Object { foo="bar"}' */
注意: String(),Number(),Boolean()被new创建或偷偷被临时转成对象,这些值任然是以单纯的数值表面存储和复制。所以即使原始值可以做类似对象一样的操作,它们的存储复制方式也不会和对象一样。
如果想完全复制一个对象,那就必须把源对象里的值获取出来并注入新的对象中。
复合值的对比
只有当两个对象指向的是同一个对象,即有相同的存储地址时,两个对象才是相等的。否则,即使两个对象看上去完全一样,它们也是不等的。
var objectFoo = {same: 'same'};
var objectBar = {same: 'same'};
/* logs false, JS does not care that they are identical
and of the same object type */
console.log(objectFoo === objectBar);
// how complex objects are measured for equality
var objectA = {foo: 'bar'};
var objectB = objectA;
console.log(objectA === objectB); /* logs true because they reference
the same object */
复合对象的动态属性
已经知道,一个变量指向一个现有的对象时并不是复制这个对象,仅仅是复制了对象的地址。所以一个对象可以拥有很多个引用对象,它们都指向同一个地址的源对象。
所以,只要这些对象中任意一个的属性改动,则其它的对象都会一起改动。
原始值和复合值的typeof 操作
值的类型要根据环境来确定。如下面,除了用new操作创建的对象外,其它快捷创建出来的值都是原始类型。
var myNull = null;
var myUndefined = undefined;
var primitiveString1 = "string";
var primitiveString2 = String('string');
console.log(typeof myNull); // logs object? WHAT? Be aware...
console.log(typeof myUndefined); // logs undefined
console.log(typeof primitiveString1, typeof primitiveString2);// logs string string
// Complex Values
var myNumber = new Number(23);
var myString = new String('male');
var myBoolean = new Boolean(false);
console.log(typeof myNumber); // logs object
console.log(typeof myString); // logs object
console.log(typeof myBoolean); // logs object
对象的可变性
因为对象拥有动态属性的特点,导致了它是可变的,即使是js的内置对象。这意味着你可以随时随地改变js中的大多数对象,改变它原配置的属性,添加属性方法等(实际上这种做法是不推荐的)。
所有的构造函数实例都有指向它们的构造函数的构造函数属性
每个实例都有一个构造函数属性,这个属性指向了构造这个实例的构造函数。
即使是原始值,也同样拥有构造函数属性,但是构造出来的并不是对象,仍是一个原始值。
var myNumber = new Number('23');
var myNumberL = 23; // literal shorthand
var myString = new String('male');
var myStringL = 'male'; // literal shorthand
console.log( // all of these return true
myNumber.constructor === Number,
myNumberL.constructor === Number,
myString.constructor === String,
myStringL.constructor === String);
如果希望自定义的对象的构造函数有确切的名字,则在定义的时候要先给它命名。如
var Person = function Person(){};
每个对象都是特定的构造函数的实例
instranceof() 函数可以用来判断一个对象是否是某个构造函数的实例。
注:1. 每个对象都是Object()构造函数的实例。
2. 如果原始值不是new出来的,则在判断构造函数实例时一定会返回false. (e.g., 'foo' instanceof
String // returns false).
构造函数构造的实例可以拥有它们独立的属性
Js中,对象随时可以被扩展。但是原始值不可以进行扩展。
var myString = new String();
var myNumber = new Number();
myString.prop = 'test';
myNumber.prop = 'test';
console.log(myString.prop,myNumber.prop); // logs 'test', 'test'
// be aware: instance properties do not work with primitive/literal values
var myString = 'string';
var myNumber = 1;
myString.prop = true;
myNumber.prop = true;
// logs undefined, undefined
console.log(myString.prop, myNumber.prop);
注: 除了构造函数的属性外,实例还会从prototype 链继承属性。如上所述,实例也可拥有自己扩展的属性。
“Javascript Objects” 和 “Object() Objects” 语义上的区别
Javascript Objects 泛指js中的所有对象,Object() Objects特指由Object构造函数构造出来的名字为Objects的对象。
后面会继续更新”第二篇 使用对象和属性“。
此文为原创,转载请附链接,谢谢。