//注:(以下this均是ES5非严格模式下的教程)很多朋友对this不是很理解,无非以下几种情况:
//① 默认情况下this指向window,函数的一般调用方式如foo();
function foo1() {
console.log(this); // window
this.bar1(); // 等价于bar1();
}
function bar1() {
console.log(this); //window
}
foo1();
//②回调函数内部的this指向window
setTimeout(function() {
console.error(this);
}, 10);
//③作为对象属性函数内部的指向
var person1 = {
name: '小明',
play: function() { //对象的play属性指代的函数的引用地址
console.log(this);
console.log(this.name);
}
}
setTimeout('person1.play()', 1000) //指向小明
setTimeout(function() {
person1.play() //指向小明
}, 1000)
person1.play(); //this指向person1, this.name==小明
var _play = person1.play; //这句话的意思是将函数的引用地址赋值给一个全局变量
_play(); //window this.name==null
//由此可见this和函数声明的位置没有任何关系,只取决于函数的调用方式,谁调用函数,this就指向谁
//④ call apply第一个参数可以改变函数内部this的指向
function foo2(num) {
console.log("foo2:" + num);
this.count++;
}
foo2.count = 0;
var i;
for(i = 0; i < 10; i++) {
if(i > 5) {
foo2.call(foo2, i);
}
}
console.log(foo2.count); //6,7,8,9 (如果不用foo2.call 那么foo2.count还是0,因为this默认指向window);
//⑤ bind 也能改变this指向
function foo3() {
console.log(this)
}
var _foo3 = {
name: '小红'
}
var _foo_3 = foo3.bind(_foo3); //foo3.call(obj)会直接执行函数了。
_foo_3(); //this会执行对象_foo3
//⑥ 原生forEach方法会改变函数内部默认this
[1, 2, 3].forEach(foo3, _foo3); //foo3里面的this指向了_foo3对象
//补充
foo3.call(null); //this指向window
console.log(Object.create(null)) //创建一个空对象,没有任何属性包括property
foo3.call(Object.create(null)) //foo3 this指向的是空对象; 更安全,传入null的话可能会是里面的this修改全局变量。危险
function xz() {
console.log(this)
}
var p = {
ww: 3,
xz: xz
}
var p2 = {
ww: 5
}
var p3 = {
ww: 7
}
p.xz(); // p
(p2.xz = p.xz)() //window
p3.xz = p.xz;
p3.xz() //p3
//⑦ new 构造函数 里面this指向实例化对象
function SFN(name) {
this.name = name;
}
SFN.prototype.play = function() {
console.log(this); //指向对象sFn
}
var sFn = new SFN('小兰');
console.log(sFn.name)
sFn.play();
//⑧立即执行函数this指向window
(function i(){
console.log("i:",this)
})()
下面引入《你不知道的js》里面一段话: