JavaScript--this的绑定规则
2018-01-27 13:25
836 查看
JavaScript中有四条调用规则,我们可以根据这四条调用规则来判断当前this的指向。
console.log(this.a);
}
var a = 2;
foo(); // 2代码很简单,那要怎么给默认绑定一个定义呢?答案就是:不带任何修饰的函数引用进行调用。
这个时候this指向window.(严格模式下指向undefined)
function foo(){
console.log(this.a);
}
var obj = {
a:2,
foo:foo
}
obj.foo(); // 2这里在调用的时候增加了一个上下文对象,隐式绑定会把函数调用中的this绑定到这个上下文对象。如果存在多层,按照最近的一层合账。a.b.c.foo(); 则实际指向的是c.
在这里呢,有一种特殊的情况,函数的赋值操作。
function foo(){
console.log(this.a);
}
function lee(func){
func();
}
var obj = {
a:2,
foo:foo
}
var a = 1;
doFoo(obj.foo); //1看似是隐式绑定,但是函数在传递参数的时候就执行了赋值操作,这个时候再次调用的绑定规则应该为默认绑定,所以指向window.
这些函数都可以直接指定this的指向,所以是显式绑定。call和apply 仍然可以通过调用时传递的参数去修改当前this的绑定,现在想象一个场景:在一个函数内部要调用一个函数,需要将这个函数绑定在一个obj对象上,但是在这个函数中无法访问到这个对象,这样一来就会产生丢失绑定的问题。这个时候可以使用硬绑定:
function foo(){
console.log(this.a);
}
var obj = {
a:2,
}
var bar = function(){
foo.call(obj);
}
bar(); //2
setTimeout(bar,100); //2
bar.call(window); //2这样一来,就无法修改函数的绑定对象了。
ES5提供了内置方法,Function.prototype.bind方法,每个function都自带bind方法,
var bar = foo.bind(obj)如此就可以使用了。
function foo(a){
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2一言以蔽之:构造一个新对象,并把它绑定到foo()调用中的this上。
多说一句:这里foo()是一个普通的函数,通过new关键字调用就是对函数的构造调用。由此可得出JS中实际上并不存在所谓的构造函数,只有对函数的构造调用。
function foo(value){
this.a = value;
}
var obj1 = {
foo:foo
}
var obj2 = {}
obj1.foo(2);
console.log(obj1.a); //2
obj1.foo.call(obj2,3);
console.log(obj2.a); //3 显式 > 隐式
--------------------------------------------
var oo1 = {};
var bar = foo.bind(oo1);
bar(2); //001.a = 2
var oo2 = new bar(3);
// oo1.a = 2,oo2.a = 3; => new > 显式之前我们看过的硬绑定的实现方式,按道理来说应该是无法修改才对的,而实际使用的时候bind()有自己的实现机制,所以new调用仍然会修改当前指向对象。
这里是传统的四种绑定方式,有没有例外呢,有。感兴趣的可以看下我总结的箭头函数对this的影响,
第一条:默认绑定。
function foo(){console.log(this.a);
}
var a = 2;
foo(); // 2代码很简单,那要怎么给默认绑定一个定义呢?答案就是:不带任何修饰的函数引用进行调用。
这个时候this指向window.(严格模式下指向undefined)
第二条:隐式绑定
隐式绑定,需要在一个对象内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把this间接绑定到这个对象上。function foo(){
console.log(this.a);
}
var obj = {
a:2,
foo:foo
}
obj.foo(); // 2这里在调用的时候增加了一个上下文对象,隐式绑定会把函数调用中的this绑定到这个上下文对象。如果存在多层,按照最近的一层合账。a.b.c.foo(); 则实际指向的是c.
在这里呢,有一种特殊的情况,函数的赋值操作。
function foo(){
console.log(this.a);
}
function lee(func){
func();
}
var obj = {
a:2,
foo:foo
}
var a = 1;
doFoo(obj.foo); //1看似是隐式绑定,但是函数在传递参数的时候就执行了赋值操作,这个时候再次调用的绑定规则应该为默认绑定,所以指向window.
第三条:显式绑定
这里呢,关于call和apply以及bind的知识,之前有说过,不清楚的可以先了解一下。这些函数都可以直接指定this的指向,所以是显式绑定。call和apply 仍然可以通过调用时传递的参数去修改当前this的绑定,现在想象一个场景:在一个函数内部要调用一个函数,需要将这个函数绑定在一个obj对象上,但是在这个函数中无法访问到这个对象,这样一来就会产生丢失绑定的问题。这个时候可以使用硬绑定:
function foo(){
console.log(this.a);
}
var obj = {
a:2,
}
var bar = function(){
foo.call(obj);
}
bar(); //2
setTimeout(bar,100); //2
bar.call(window); //2这样一来,就无法修改函数的绑定对象了。
ES5提供了内置方法,Function.prototype.bind方法,每个function都自带bind方法,
var bar = foo.bind(obj)如此就可以使用了。
第四条:new绑定
也就是通过new去实例化一个对象。、function foo(a){
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2一言以蔽之:构造一个新对象,并把它绑定到foo()调用中的this上。
多说一句:这里foo()是一个普通的函数,通过new关键字调用就是对函数的构造调用。由此可得出JS中实际上并不存在所谓的构造函数,只有对函数的构造调用。
优先级:
说了四种方式,既然存在那难免就会有个比较,到底谁更优先呢?function foo(value){
this.a = value;
}
var obj1 = {
foo:foo
}
var obj2 = {}
obj1.foo(2);
console.log(obj1.a); //2
obj1.foo.call(obj2,3);
console.log(obj2.a); //3 显式 > 隐式
--------------------------------------------
var oo1 = {};
var bar = foo.bind(oo1);
bar(2); //001.a = 2
var oo2 = new bar(3);
// oo1.a = 2,oo2.a = 3; => new > 显式之前我们看过的硬绑定的实现方式,按道理来说应该是无法修改才对的,而实际使用的时候bind()有自己的实现机制,所以new调用仍然会修改当前指向对象。
这里是传统的四种绑定方式,有没有例外呢,有。感兴趣的可以看下我总结的箭头函数对this的影响,
相关文章推荐
- 你不知道的javascript之this的全面解析之绑定规则(一)
- JavaScript中this的四个绑定规则总结
- JavaScript的回调函数内部this的指向问题以及四种绑定this指向的方法
- javascript 切换上下文,事件绑定中改变this指向
- javascript的函数上下文this四条规则
- Javascript事件绑定this
- javascript的动态this与动态绑定
- Javascript中的this绑定
- 【javascript】函数中的this的四种绑定形式 — 大家准备好瓜子,我要讲故事啦~~
- 浅谈javaScript的 this指向重绑定 与 函数自执行用法 与 自执行指向
- javascript事件绑定的this
- javascript事件绑定后this变义问题的解决[prototype1.5.1]
- javascript下动态this与动态绑定实例代码
- javascript 函数中的 this 的四种绑定形式
- 学习javascript的动态this指针与动态绑定 call与apply函数的应用
- javascript事件绑定后this变义问题的解决[prototype1.5.1]
- JavaScript中this对象的绑定
- 深入理解this机制系列第一篇——this的4种绑定规则
- 【javascript】函数中的this的四种绑定形式
- Javascript 绑定事件和 this理解