js动态调用特性

JS 的动态调用特性是 JS 动态特性中重要的组成部分,提到这个特性就需要讲明白bindcallapply这三个函数

JS函数的调用机制

js 里函数调用有 4 种模式:方法调用、正常函数调用、构造器函数调用、apply/call 调用。无论哪种函数调用除了你声明时定义的形参外,还会自动添加 2 个形参,分别是 this 和 arguments。arguments 是一个 array-like 类型对象,提供了 length 和下标操作符访问元素的方法,但是却没有提供其他任何数组对象应有的方法。

this 到对象的绑定是一个超级延迟绑定,这个绑定发生在函数调用的时候,this 代表的也就是主调方对象。这实现了 JS 的强大动态特性。

方法调用

如果函数是对象的属性,那么对函数的调用成为方法调用。通过对象点语法调用方法时,函数内部的 this 指针将指向对象本身。

函数调用

如果函数不是对象的属性,那么对函数的调用就叫做函数调用,内部的 this 指针指向任何调用这个函数的对象,如果有如下情况:

1
2
3
4
5
function a(m) {
this.x = m;
}

a(2);

按照 JS 的坑爹尿性这样的调用会导致,window 对象被添加上 x 属性并被赋值为 m,这里需要谨慎。

构造器函数调用

按照约定,构造器函数如下方式定义,通过 new 关键字进行调用。因为构造器函数调用会导致与其他函数调用不同的效果,所以构造器函数的首字母需要大写来和普通函数进行区分,这非常重要。

1
2
3
4
5
var Cons = function () {
//do something
}

var cons = new Cons();

使用new关键字调用构造器函数且返回值不是对象时,函数会背地里生成一个链接到函数 prototype 成员的新对象,同时将 this 指针绑定到这个对象上面。new 关键字也会改变 return 的语义,如果构造器函数返回值不是对象,则会返回 this 指针(即新对象)。

来看这三个函数

apply

apply 接受两个参数,第一个参数是想要让 this 绑定到的对象,第二个参数是一个数组,里面存放想要传递个函数的参数。
使用 apply 函数,你就可以把任意的对象赋给被调函数内部的 this 指针,这样一来动态性就有变态般的提升了。
第一个参数为 null 时,this 指针已然是当前的 this 指向的1对象。

1
2
3
4
5
6
7
function a(xx) {        
this.b = xx;
}
var o = {};
a.apply(o, [5]);
alert(a.b); // undefined
alert(o.b); // 5

call

call 和 apply 几乎相同,只是 call 的参数是不定参数,第一个参数代表的依然和 apply 一样,只是参数数组变成了多个参数的形式传入。

1
2
3
4
5
6
7
function a(xx,yy) {        
this.b = xx + yy;
}
var o = {};
a.call(o, 5, 6);
alert(a.b); // undefined
alert(o.b); // 11

bind

bind 的参数和以上两个函数一致,只是不会像他们一样马上发生函数调用,bind 只是将对象绑定给 this 指针,然后返回新的函数,想什么时候调就什么时候调。

1
2
3
4
5
6
7
8
9
10
var m = {   
"x" : 1
};
function foo(y) {
alert(this.x + y);
}
foo.apply(m, [5]);
foo.call(m, 5);
var foo1 = foo.bind(m, 5);
foo1();

应用:

apply,call 可以用到构造函数的继承上。
使用方法参见:
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html