创建和访问
JavaScript 中的对象实际上就是一个由属性组成的关联数组,属性由名称和值组成,值的类型可以是任何数据类型,或者函数和其他对象。
var foo = {};// 也可以用 var foo = new Object() 来显式地创建一个对象。 foo.prop_1 = 'bar'; foo.prop_2 = false; foo.prop_3 = function(){ return 'hello world'; } document.write(foo.prop_3());
我们还可以用关联数组的模式来创建对象,以上代码修改为:
var foo = {}; foo['prop_1'] = 'bar'; foo['prop_2'] = false; foo['prop_3'] = function(){ return 'hello world'; } document.write(foo.prop_3());
真正在使用的时候,我们会采用下面这种更加紧凑明了的方法:
var foo = { 'prop1': 'bar', 'prop2': false, 'prop3': function(){ return 'hello world'; } } document.write(foo.prop3());
构造函数
以上对象创建方法都有一个弱点,就是创建对象的代码是一次性的。如果我们想创建多个规划好的对象,有若干个固定的属性、方法,并能够初始化,该如何做呢?
function User(name, uri){ this.name = name; this.uri = uri; this.display = function(){ document.write(this.name); } } var user1 = new User('lzl', 'http://www.lzl.com'); user1.display();
上下文对象
在JavaScript 中,上下文对象就是 this 指针,即被调用函数所处的环境。在前面使用构造函数的代码中我们已经看到了 this 的使用方法,下面代码可以更佳清楚地说明上下文对象的使用方式:
var someuser = { name: 'lzl', display: function(){ document.write(this.name); } } someuser.display();// lzl var foo = { bar: someuser.display, name: 'foobar' } foo.bar();// foobar name = 'global'; func = someuser.display; func();// global
仔细观察上面的例子,使用不同的引用来调用同一个函数时,this 指针永远是这个引用所属的对象。
call 和 apply
call 和 apply 的功能是以不同的对象作为上下文来调用某个函数。简而言之,就是允许一个对象去调用另一个对象的成员函数。两者的功能是一致的,细微的差别在于 call 以参数表来接受被调用函数的参数,而 apply 以数组来接受被调用函数的参数。
func.call(thisArg[, arg1[, arg2[, ...]]])
func.apply(thisArg[, argsArray])
func 是函数的引用,thisArg 是 func 被调用时的上下文对象,arg1、arg2 或argsArray 是传入 func 的参数。
var someuser = { name: 'lzl', display: function(words){ document.write(this.name + ' says ' + words); } } var foo = {name: 'foobar'}; someuser.display.call(foo, 'hello');// foobar says hello 通过 call 将上下文改变为 foo 对象,因此在函数体内访问 this.name 时,实际上访问的是foo.name,因而输出了foobar。 someuser.display.apply(foo,['hello']);// foobar says hello
bind
可以用 call 或 apply 方法改变被调用函数的上下文,但如果重复使用会不方便,因为每次都要把上下文对象作为参数传递,而且还会使代码变得不直观。针对这种情况,我们可以使用 bind 方法来永久地绑定函数的上下文,使其无论被谁调用,上下文都是固定的。bind 语法如下:
func.bind(thisArg[, arg1[, arg2[, ...]]])
var someuser = { name: 'lzl', display: function(){ document.write(this.name); document.write('<br>'); } } var foo = {name: 'foobar'}; foo.func = someuser.display; foo.func();// foobar foo.func1 = someuser.display.bind(someuser); foo.func1();// lzl name = 'global'; func = someuser.display.bind(foo); func();// foobar func2 = func; func2();// foobar
上面代码直接将 foo.func 赋值为 someuser.display,调用 foo.func() 时,this指针为foo,所以输出结果是foobar。foo.func1 使用了bind 方法,将someuser 作为this指针绑定到someuser.display,调用 foo.func1() 时,this指针为someuser,所以输出结果是lzl。全局函数func 同样使用了bind 方法,将foo 作为this 指针绑定到 someuser.display,调用 func() 时,this 指针为 foo,所以输出结果是 foobar。而 func2 直接将绑定过的func 赋值过来,与func 行为完全相同。