对象类似自定义键值类型的数组。
数组文本标识法:[]定义数组。
对象文本标识法:{}定义对象。
目录
一.定义对象的几种方法:
1.对象标识法
var Leo = {
name : 'Leo';
'age' : 0;
'talk' : function(){
return 'I am ' + Leo.name; //或this.name
}
};
2.构造器函数
即通过函数的方法来构造对象。需要利用new来进行实例化。
function Person(name){
this.name = name;
this.age = 0;
this.talk = function(){
return "I am " + this.name;
}
}
var Leo = new Person('Leo');
全局变量是宿主环境的对象。如当宿主环境是浏览器时提供的宿主环境就是window。在构造器函数之外使用this即可以调取全局对象。对由new创建的对象使用typeof返回 应是Object。
3.构造器属性
当一个对象创建的时候实际上同时赋予了该对象一特殊的“构造器属性”。构造器属性是一个指向用于创建该对象的构造器函数的引用。
如打印Leo.construtor ,则会返回funtion Person(){...}。
另外一种定义对象的方法可以直接通过另一对象的构造器属性来实现。
如
var Ann = new Leo.constructor('Ann');
>Ann.name;
-"Ann"
此外,如果对象是通过对象文本标识法创建的,那么实际上它是由内件构造器Object()函数说创建的。因此,如果
var o = {};
打印>o.constructor,
返回应是
-function Object(){ [native code] }
【instanceof 操作符】
instanceof函数可用于测试对象是否是某个指定的构造器函数创建的。比如
> Leo instanceof Person;
-true.
>var p = {};
>p instanceof Object;
-true.
值得一提的是,如果打印Leo instanceof Object,仍旧会打印出true。
如果不适用new 关键字,只用一般函数来创建对象,就需要一个能够执行某些预备工作并以对象为返回值的函数。
如
function Person(name){
return {
name : name;
};
}
之后,调用Person函数来生成对象:
var Chris = Person('Chris');
不过创建的这个Chris的构造器仍然是Object。
> Chris.constructor;
- function Object(){ [native code] }.
事实上,构造器函数也是可以返回对象的,只不过在this值的使用上会有所不同,这意味着我们需要修改构造器函数的默认行为。如:
function C(){
this.a = 1;
return {b : 2};
}
var c = new C();
那么,当我们试图打印 >typeof c.a 的时候,就会返回undefind,而打印 >c.b 的时候,则会返回2。
此时,构造器返回的不再是包含属性a 的this对象,而是一个包含属性b的对象。【注意,return语句中使用大括号,说说明{b:2}是一个独立的对象。】当然,这也只在函数的返回值是一个对象的时候才会发生,而当我们企图返回一个非对象类型时,该构造器会照常返回this。
二.传递对象、比较对象
1.传递对象
【注】当我们传递某个对象或者将它传递给某个函数时,往往传递的都是对象的引用。在引用上所做的所有改动,都会影响到引用的原对象。(无论是赋值还是将对象作为参数进行传递时)
如
> var origin = {num : 1};
> var copy = origin;
> copy.num;
- 1
> copy.num = 100;
> origin.num;
- 100;
以及
> var origin = (num : 100);
> var zer = function(o) {o.num = 0;}
> zer(origin);
> origin.num
- 0;
我暂时对这个机制还有一些匪夷所思,并且觉得不是非常合理,但是这的确应该成为编写对象传递时变量安全性的同时需要注意的很关键的一点。
2.比较对象
仅当两个引用指向同一个对象时,对它们进行===运算能够返回true。如果指向的是不同的对象,即使他们的属性值刚巧一样也会返回false。
三.Object对象
Object对象时所有对象的父级对象,所有的对象都继承于Object。再创建一个空对象时,使用对象文本标识法var o = {}的效果与var o = new Object()是等同的。而我们创建“空”对象的时候,实际上这个空对象也具有了继承而来的方法和属性。(包括.constructor在内)
此外,还有很多常见的构造器函数比如Array()、Function()等。
在使用Function做构造器来创建函数对象时,参数需要通过参数传递的方式设定函数的参数名。以下几种定义函数的方式是相同的:
1.
function sum(a, b){
return a + b;
}
2.
var sum = function(a, b){
return a + b;
};
3.
var sum = new Function('a', 'b', 'teturn a + b;');
四.函数对象的属性
1.constructor
与其他对象相同,函数对象中也含有constructor属性,其引用的就是Function()这个构造器函数。
2.length
用于记录该函数声明时所决定的参数数量。
3.prototyp属性
用得最广泛的属性。
五.函数对象的方法
1.继承来的方法
由于函数都继承于顶级父对象Object,因此也具有Object对象的一切方法,如toString()、valueOf()、constructor()等。
2.call()和apply()
call()
每个js函数都具有这两个方法,可以实现简单而且实用的代码重用,让一个对象去借用另一个对象的方法,并为自己所用。简单来说,就是把另外一个对象的某部分作为参数传入这个函数的一个方法中或者将一个对象的引用传入,改变this的指向。(p122)这是一个非常有意思也很巧妙的使用。
比如:
var Bob = {
name : 'Bob';
talk : function(who){
return 'hi' + who + 'I am ' + this.name;
}
};
这样,如果这样调用
> Bob.talk('You')
就会打印
- "hi You I am Bob"
再创建一个只有名字的对象
var Cath = (
name : 'Cath';
};
我们希望将Bob的talk方法也当做Cath自己的方法来用,就可以使用talk()函数的对象方法call()。
> Bob.talk.call(Cath, 'You');
- "Hi You, I am Cath"
call()函数传入两个值,把Cath对象传了进去。当talk()被调用的时候,其中的this被自动设置成了Cath对象的引用。因此我们可以看到this.name已经不是Bob而是Cath了。
如果调用call()方法时需要传递更多的参数,可以在后面依次加入它们。但是,我们如果没有吧对象传递给call()函数的首参数,或者传递给它的是null,它的调用对象将会被默认为全局对象。
apply()
apply()函数与call()函数的使用基本相同,但是目标函数所需要的参数都是通过一个数组来传递的。
以下两种方式等价:
1.
Bob.call(Cath, 'a', 'b', 'c');
2.
Bob.apply(Cath, ['a', 'b', 'c']);
因而,前面的案例也可以写成
Bob.talk.apply(Cath, ['You'])。
应用1:arguments对象
我们知道,arguments对象作为函数的内建对象看起来是一个数组,实际上却是一个数组对象,不提供sort()、slice()等的方法。但我们可以把arguments转换成数组,对其使用数组的方法。如:
function f(){
var args = [].slice.call(arguments);
return args.reverse;
}
> f(1,2,3,4);
- [4,3,2,1]
这里的做法事新建一个空数组,再使它的slice属性。当然同理也可以通过Array.prototype.slice来调用同一个函数。
【存疑】
应用2:推断对象类型
.数组以及对象数组(就像上面的arguments)的typeof关键字返回值都是Object,想要具体区分就需要用到toString()方法。这个方法会返回创建对象的内部类名。比如:
> Object.prototype.toString.call({});
"object Object"
> Object.prototype.toString.call([]);
"object Array"
在这里,toString()方法必须要来自Object构造器的prototype属性。直接调用Array的toString()方法是不行的,因为在Array对象中这个方法已经处于别的目的被重写了。
(p124)
五.一些内建对象
除了string、number、boolean之外,
还有:
1.Math
不是函数对象。包括一些Math.PI、Math.SQRT2、Math.LN10等的数值。
2.Date
用于创建Date对象的构造器函数。在创建它的时候可以传递下列参数:
①无参数(默认当天的日期)
②一个用于表现日期的字符串
③分开传递的日月时间等值
④一个timestamp值。
3.RegExp
即正则表达式。正则表达式提供了一种强大的文本搜索和处理方式。js采用了Perl5的语法。