绑定规则
默认绑定
独立函数调用( 独立函数:不加任何修饰的)
其他规则不适用时
1)非严格模式下定义函数,默认绑定到window
function fun() {
console.log(this.a);
}
var a = 2;
fun(); //2
2) 严格模式下定义函数,默认绑定到undefined
function fun() {
"use strict";
console.log(this.a);
}
var a = 2;
fun(); //TypeError:this is no undefined
特别地,
严格模式下调用函数 ,依然默认绑定到window
function fun() {
console.log(this.a);
}
var a = 2;
(function () {
"use strict";
fun(); //2
})();
隐式绑定
用于:调用位置有上下文对象,被某个对象拥有
当被调用时,foo函数的this会绑定到obj(上下文对象);故this.a和obj.a一样
foo无论是直接在obj中定义,还是先定义再添加为obj引用属性,严格说foo函数不属于obj对象
// foo:function object Oriented面向对象函数
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo,
};
obj.foo();//2
对象属性引用链仅最后一层在调用位置中作用
function foo() {
console.log(this.a);
}
var obj2 = {
a: 42,
foo: foo,
};
var obj1 = {
a: 2,
obj2: obj2,
};
obj1.obj2.foo(); //42
隐式丢失
例1解析:
bar是obj.foo的一个引用,但实际引用的是foo函数
bar()是独立函数调用,应用了默认绑定
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo,
};
// 函数别名
var bar = obj.foo;
//a是window的属性
var a = "oops,global";
bar(); //oops,global
例2:回调函数
参数传递是一种隐式赋值,故传入函数也会被隐式赋值
function foo() {
console.log(this.a);
}
function doFoo(fn) {
// fn引用的是foo
fn();
}
var obj = {
a: 2,
foo: foo,
};
var a = "oops,global";
doFoo(obj.foo); //oops,global
显式绑定
对象内部不包含引用的情况下,在对象上强制调用函数
方法:
call()
apply()
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
};
foo.call(obj);//2
隐式丢失的解决方法-硬绑定
是一种显式的强制绑定
特点:
1.无论以何种方式调用(独立函数调用、回调函数),都会手动在绑定对象上调用函数
2.不能再修改绑定
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
};
//创建bar函数
var bar = function () {
// 手动调用
// 将foo的this强制绑定到obj
foo.call(obj);
};
// 硬绑定后,独立函数调用会手动在obj调用foo
bar(); //2
// 硬绑定后,回调函数仍会手动在obj调用foo
setTimeout(bar, 100); //2
// 硬绑定后,不能再修改绑定
bar.call(window); //2
优化:辅助函数-可重复使用
function foo(something) {
console.log(this.a, something);
return this.a + something;
}
var obj = {
a: 2,
};
// 辅助函数
function bind(fn, obj) {
return function () {
return fn.apply(obj, arguments);
};
}
var bar = bind(foo, obj);
var b = bar(3); //2 3
console.log(b); //5
优化:ES5内置方法Function.prototype.bind
function foo(something) {
console.log(this.a, something);
return this.a + something;
}
var obj = {
a: 2,
};
var bar = foo.bind(obj);
var b = bar(3); //2 3
console.log(b); //5
隐式丢失的解决方法-API调用的‘上下文’
指第三方库的函数、JavaScript和宿主环境中的内置函数,提供可选参数context上下文
本质通过call()\apply()实现了显示绑定
例如:forEach
function foo(el) {
console.log(el, this.id);
}
var obj = {
id: "awesome",
};
[1, 2, 3].forEach(foo, obj);
//1 'awesome' 2 'awesome' 3 'awesome
new绑定
事实上,不存在构造函数;只有对函数的’构造调用’
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2
优先级
new绑定——显式绑定——隐式绑定——默认绑定
具体规则
规则 | 上下文 |
---|---|
对象.方法() | 对象 |
函数() | window |
数组[下标]() | 数组 |
IIFE | window |
定时器 | window |
DOM事件处理函数 | 绑定DOM的元素 |
call和apply | 任意指定 |
规则1-对象.方法()-对象
例1
function fn(){
console.log(this.a+this.b);//99
}
var obj={
a:66,
b:33,
fn:fn
};
obj.fn();
例2
var obj1={
a:1,b:2,fn:function(){
console.log(this.a+this.b);//7
}
};
var obj2={
a:3,
b:4,
fn:obj1.fn
};
obj2.fn();
例3
function outer() {
var a = 11;
var b = 22;
return {
a: 33, b: 44, fn: function () {
console.log(this.a + this.b);//77
}
};
}
outer().fn();
例4
function fun() {
console.log(this.a + this.b);//7
}
var obj = {
a: 1,
b: 2,
c: [{
a: 3, b: 4, c: fun
}]
};
var a = 5;
obj.c[0].c();
//obj.c[0]对应对象[{a: 3, b: 4, c: fun}]
规则2-函数()-window
例1:方法赋值给全局变量fn,全局调用fn
var obj1={
a:1,
b:2,
fn:function(){
console.log(this.a+this.b);//7
}
};
var a=3;
var b=4;
var fn=obj1.fn;
fn();
例2:第一层-obj.fun(),this指代obj;第二层-fun(),this指代window
function fun(){
return this.a+this.b;
}
var a=1;
var b=2;
var obj={
a:3,
b:fun(),
fun:fun
};
var result=obj.fun();
console.log(result);//6
规则3-数组[下标]()-数组
例1
var arr=['A','B','C', function(){
console.log(this[0]);//'A'
}
];
arr[3]();
例2
function fun(){
arguments[3]();
}
fun('A','B','C',function(){
console.1og(this[1]);//B
}
);
规则4-IIFE-window
var a=1;
var obj={
a:2,
fun:(function(){
var a=this.a;//this-window;this.a-1
return function(){
console.log(a+this.a);//this-obj;this.a-2;输出3
}
})()
};
obj.fun();
规则5-定时器、延时器-window
◆规则5:定时器、延时器调用函数,上下文是window对象
setInterval(函数,时间);
setTimeout(函数,时间);
规则5题目举例
var obj={
a:1,b:2,fun:function(){
console.log(this.a+this.b);
}}
vara=3;varb=4;
setTimeout(obj.fun,2000);适用规则5
输出7
var obj={
a:1,b:2,fun:function(){
console.log(this.a+this.b);
}}
vara=3;varb=4;
setTimeout(function(){
obj.fun();//适用规则1
},2000);
输出3
规则6-DOM绑定事件-绑定事件的DOM元素
DOM元素.onclick=function(){
};
案例1:请实现效果:点击哪个盒子,哪个盒子就变红,要求使用同一个事件处理函数实现
案例2:请实现效果:点击哪个盒子,哪个盒子在2000ms就变红,要求使用同一个事件处理函数实现
规则7-call&apply-任意指定
两者区别:
call逗号罗列参数;apply数组罗列参数
function sum(b1,b2){
alert(this.c+this.m+this.e+b1+b2);
}
sum.cal1(xiaoming,5,3);
sum.apply(xiaoming,[5,3]);
argument作为参数,用apply
function fun1(){
fun2.apply(this,arguments);
}
function fun2(a,b){
alert(a+b);//77
}
fun1(33,44);