从JS库的使用者转变成JS的开发者——第一篇 javascript对象

此文是《Javascript Elightment》的读书笔记,希望和有意向从jS库的使用者转变成js的开发者的童鞋们一起分享。

创建对象

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的对象。

后面会继续更新”第二篇 使用对象和属性“。

此文为原创,转载请附链接,谢谢。