JavaScript中this的绑定
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<h5><a id="this_0"></a>this指向问题</h5>
在javascript
中this
绑定有以下几种方式
默认绑定
function foo(){
console.log(this.a);
}
var a = 1;
foo(); // 1
以上绑定代码即为this的默认绑定,当函数没有其他绑定时,此时this指向window对象;
隐式绑定
隐式绑定需要考虑的是调用位置是否有上下文对象.如下代码所示:
function foo(){
console.log(this.a);
}
var obj = {
a:'obj',
foo:foo
}
obj.foo(); // obj
在上述代码中foo
函数作为一个值被赋予到了obj
对象的foo
属性中,此时的this
指向obj
这个对象,调用时
打印的this.a
为obj.a
为obj;再如下代码
function foo() {
console.log(this.a);
}
var obj2 = {
a: 'obj2',
foo: foo
}
var obj1 = {
a: 'obj1',
obj2: obj2
}
obj1.obj2.foo(); // obj2
foo
函数是obj2
中foo
属性的值,上述代码中obj1
通过调用自己的obj2
属性来调用obj2.foo
,打印出的值是obj2
,可见对对象属性引用链中只有上一层或者说是最后一层在调用位置起作用
隐式丢失
在隐式绑定中存在隐式丢失这个问题,被隐式绑定的函数会丢失其隐式绑定对象,也就是说此时函数会应用默认绑定,从而把this绑定到全局对象或者undefined
上,取决于是否为严格模式;
function foo() {
console.log(this.a);
}
function doFoo(fn) {
fn();
}
var obj = {
a: 'obj',
foo: foo
}
var a = 'global this';
doFoo(obj.foo); // global this
doFoo.call(window,obj.foo); // global this
在上述代码中调用doFoo
传入obj.foo
此时fn=obj.foo
(在AO对象中)可以看作一个隐式赋值,此时doFoo
的this
指向window
,所以打印出来golbal this
如果把函数传入语言内置的函数而不是自己声明的函数,结果是一样的,比如setTimeout
函数:
setTimeout(obj.foo,100); // global this
// 伪代码如下
// function setTimeout(fn,delay) {
// // 等待delay
// fn();
// }
显示绑定
显示绑定可以借助call
,apply
函数完成,代码如下:
function foo(){
console.log(this.a)
}
var obj = {
a:'obj'
}
foo.call(obj); // obj
foo.apply(obj); // obj
通过调用call
或apply
可以在调用foo
时前置把它的this
绑定到obj
上;
在这里还有个概念装箱
:如果传入了一个原始值(字符串类型,布尔类型或者数字类型)来当做his的绑定对象,这个原始值会被转换成它对应的对象形式(new String()
…).
但显示绑定也无法解决丢失绑定的问题,此时显示绑定的一个变种硬绑定可以解决这个问题
硬绑定
function foo() {
console.log(this.a);
}
var obj = {
a: 'obj'
}
var bar = function () {
return foo.call(obj)
}
bar();
在上述代码中创建了一个bar
函数,每次调用bar
都会在obj
上调用foo
这种绑定是一种显示强制绑定,称之为硬绑定.
硬绑定的典型应用场景就是创造一个包裹函数,负责接收参数并返回值,由于硬绑定是一种非常常用的模式,所以es5
提供了内置方法Function.prototype.bind
,应用方法如下
function foo(something) {
console.log(this.a + something);
}
var obj = {
a: 'obj'
}
foo.bind(obj)(' something'); // obj somehing
bind
会返回一个硬编码的函数,它会把指定参数者只为this
上下文并调用原始函数;
new绑定
function foo(a){
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); // 2
使用new
调用foo
时会构造一个新对象并把它绑定到foo
调用中的this
上.new
是最后一种可以影响函数调用时this
绑定行为的方法.
读《你不知道的JavaScript 上卷》笔记记录