Open nicoleJT914 opened 7 years ago
踩坑Array.prototype.forEach
array.forEach(callback(currentValue, index, array){
//do something
}, this)
forEach还有参数this
,不指定的话默认是undefined
因此要么提前绑定this,要么在forEach中指定this
怎样在定时器setTimeout
中锁定this
?
用bind()
呀!
setTimeout(fn.bind(this), xx)
Ps: 顺便提一句,关于怎样在setTimeout
中使用传递参数的函数
// 回调函数
function callback(element) {}
// 对回调函数形式进行修改
setTimeout(fn(element), xx)
function fn(element) {
return callback() {
}
}
SO上有关于this
的运用,已经比较清楚了
How to access the correct this
context inside a callback?
最上面关于this的解释太麻烦了,重新梳理一下
function Foo() {
this.name = 'jack',
this.age = 35
console.log(this)
}
Foo.prototype.say = function() {
console.log(this.name)
}
var foo = new Foo()
foo.say()
console.log(foo.name)
console.log(foo.age)
若函数为构造函数,则this
指向实例化的对象
当函数作为对象的一个属性并且被直接调用时,函数中的this
指向该对象
var o = {
x: 10,
fn: function() {
console.log(this) // o
console.log(this.x)
}
}
o.fn()
注意:只有直接调用才指向该对象
var o = {
x: 10,
fn: function() {
console.log(this) // Window
console.log(this.x)
}
}
var s = o.fn
s()
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function(fn) {
fn();
// 实质上是arguments对象属性的读取,所以this是arguments对象
arguments[0]();
}
};
obj.method(fn, 1);
// result should be 10 2
this
的作用随着使用模式越来越复杂,显式传递上下文对象会让代码变得越来越混乱 而
this
提供了一种更隐式方式来传递一个对象引用,使得代码的复用性提高this
的绑定规则默认绑定
无法应用其他规则时的默认规则(也是坑最多的地方)
如果函数体(注意!是函数体,并不是调用位置处于严格模式)处于严格模式,对于默认绑定,this会被绑定到undefined(而不是全局对象)。
隐式绑定
当函数引用有上下文对象时,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象。
显式绑定
隐式绑定时,我们必须在一个对象内部包含一个指向函数的属性,并通过这个属性调用函数,从而把 this 绑定到这个对象上。 如果我们不想在对象内部包含函数引用,而想在某个对象上强制调用函数,则需要使用
call()
和apply()
方法第一个参数是一个对象,它们会把这个对象绑定到 this,接着在调用函数时指定这个 this。
如果传入了一个原始值(字符串类型、布尔类型或者数字类型)来当作 this 的绑定对象,这个原始值会被转换成它的对象形式(也就是new String(..)、new Boolean(..)或者 new Number(..))。这通常被称为“装箱”。
为什么我们需要一个函数将foo.call(obj)包起来呢?为什么像下面这样做
因为setTimeout传入的参数应该是一个函数,而
foo.call(obj)
是会直接调用函数的,这样定时器并不能起到作用!!所以才会把foo.call(obj)
包到一个函数里ES5中提供了内置方法
Function.prototype.bind
:bind()
会返回一个硬编码的新函数,它会把参数设置为 this 的上下文并调用原始函数,要注意bind()
会返回新函数,但并不会像apply()
和call()
一样会直接调用函数,所以bind()
更常用为回调函数指定thisnew绑定
new来
调用,称为“构造函数调用”。JS中并不存在所谓的“构造函数”,只有对于函数的“构造调用”
4条绑定规则的优先级
比较 隐式绑定 和 显示绑定
显示绑定的优先级更高
比较 new绑定 和 隐式绑定
} obj1.foo(2) console.log(obj1.a) // 2
obj1.foo.call(obj2, 3) console.log(obj2.a) // 3 console.log(obj1.a) // 2
var bar = new obj1.foo(4) console.log(obj1.a) // 2 console.log(bar.a) // 4
function foo(something) { this.a = something; } var obj1 = {}; var bar = foo.bind(obj1); bar(2); console.log(obj1.a); // 2 var baz = new bar(3); console.log(obj1.a); // 2 console.log(baz.a); // 3
function foo(p1, p2) { this.val = p1 + p2 } var bar = foo.bind(null, "p1") var baz = new bar("p2") baz.val // p1p2
function foo(a, b) { console.log("a:" + a + ",b:" + b) } // 使用 null 来忽略 this 绑定 foo.apply(null, [1, 2]) var bar = foo.bind(null, 5) bar(6)
function foo(a, b) { console.log("a:" + a + ",b:" + b) } foo(...[1,2])
function foo(a, b) { console.log("a:" + a + ",b:" + b) } var ø = Object.create(null) foo.apply(ø, [2, 3]) var bar = foo.bind(ø, 2) bar(3)