目录
part1:
part2:
part3:
问题5: this总是指向事件的触发者还是事件的绑定者?触发者和绑定者不一样时?
法则:
1. this指向的永远是一个对象
2. 指向的是哪个对象,取决于谁调用了它
例题1:
问obj.f()打印的是什么?
function fun() {
console.log(this.s);
}
var obj = {
s: 1,
f: fun
}
var s = 2;
obj.f();
打印的是1;
原因是:
1. obj.f表示调用obj对象里面的f方法,
2. f指向fun这个函数,上面的式子可以改成下面的式子
function fun() {
console.log(this.s);
}
var obj = {
s: 1,
f: function () {
console.log(this.s); // 看这里
}
}
var s = 2;
obj.f();
因此直接理解为obj对象调用本身的方法,this指向obj这个对象。
例题2:
问直接调用fun(),输出的是什么?
function fun() {
console.log(this.s);
var obj = {
s: 1,
f: fun
}
var s = 2;
fun();
- s是2
- 因为是window调用fun()函数。而不是obj调用,尽管obj里面的f指向fun函数
- 所以this指向window这个对象
- 而s=2是全局作用域的变量
例题3:
问A.f()和B.f()分别输出的什么?
var A = {
name: 'jmq',
f: function () {
console.log(this.name);
}
};
var B = {
name: 'syc',
};
B.f = A.f;
A.f();
B.f();
A.f()输出的是jmq,
B.f()输出的是syc
为什么?
关键看懂B.f = A.f()是什么意思?
意思是A里面的f方法赋值给B,是赋值的意思!!类似下图的结果
var A = {
name: 'jmq',
f: function () {
console.log(this.name);
}
};
var B = {
name: 'syc',
f: function () {
console.log(this.name); // 看这里
}
};
B.f = A.f;
A.f(); // jmq
B.f(); // syc
而A和B各自调用本身的方法f,this指向的就是本身
例题4:
和例3相似的题目,例3理解了,这题也可以理解
// 问最终的结果输出的是什么?
function fo() {
console.log(this.a);
}
var o1 = {
a: 3,
};
var o2 = {
a: 6,
};
var a = 9;
o1.f = fo;
console.log(o1);
o2.f = o1.f;
o1.f(); // 输出什么?
o2.f(); // 输出什么?
o1.f()输出3
o2.f()输出6
为什么?对于o1和o2的操作和例3类似,本质还是赋值。可以看成下面的代码
// 问最终的结果输出的是什么?
function fo() {
console.log(this.a);
}
var o1 = {
a: 3,
// f: function fo() {
// console.log(this.a);
// }
};
var o2 = {
a: 6,
// f: function fo() {
// console.log(this.a);
// }
};
var a = 9;
o1.f = fo;
console.log(o1);
o2.f = o1.f;
o1.f(); // 3
o2.f(); // 6
// 为什么?
// 跟之前一题很相似,给o1增加fo方法,同时通过o2.f = o1.f;让o2也有这个方法
// 那么就是对象调用方法,this指向对象
例题5:
问最终输出的是几?
// 问最终的结果输出是几?
function foo() {
console.log(this.a);
}
var obj2 = {
a: 2,
fn: foo
};
var obj1 = {
a: 1,
o1: obj2
};
obj1.o1.fn(); // 输出的是啥?
结果:
输出的是2.
· 为什么是2?根据法则:this指向的一定是一个对象,关键是指向了哪个对象?
· obj1.o1本质上是obj2,所以,据此判断就是obj2调用了foo函数,
· 就是指向obj2,里面a是2
this不仅仅是指向调用的对象,指向的还是调用的最近一级的对象
例题6:
var a = 10;
var obj = {
a: 120,
method: function () {
var bar = function () {
console.log(this.a); // 输出什么?
};
bar();
return this.a; // 输出什么?
}
}
console.log(obj.method());
第一个this.a输出是10
第二个this.a输出是120
为什么?
第一个this.a:
首先, 第18行输出10,关键看bar这个函数是谁调用的,是window调用的。
其次, 为什么是window调用的?
再者, 仔细观察,只是在obj里面的方法里面声明了一个函数,在方法里面调用了函数,可以理解为obj调用了method,但是obj并没有直接调用bar。
最后, 是window调用了bar。指向window,所以是10
第二个this.a:
return this.a;因为是在method里面return this,而是obj调用的method方法,所以this指向obj,打印的是120
总结:
1. 对象调用了方法,那么this指向对象。如例1例3例4
2. 全局下执行函数,this指向window,如例2
3. 如obj1.o1.fn(),假如
对象调用了自己的一个属性o1,o1的属性值指向另外一个对象obj2,obj2的fn又是一个函数,这个函数里面打印this,this指向最近的obj2
4. 如果一个对象里面的方法1,方法里面还有一个函数2,函数2在对象的方法1里面执行,函数2打印this,指向的全局window,而不是这个对象。
这篇文章只需要额外理解第四个即可,其他的都按照我的第一个文章里面列举的去理解即可。
javascript 高级编程 this指向问题【1】_hangshao_123的博客-优快云博客
part2:
例题7:
var fullName = 'language';
var obj = {
fullName: 'javascript',
prop: {
getFullName: function () {
return this.fullName;
}
}
};
console.log(obj.prop.getFullName()); // 这里输出什么?
var test = obj.prop.getFullName;
console.log(test()); // 这里输出什么
第一个地方输出undefined
第二个地方输出language
1. 为什么第一个地方指向undefined?
1.1 obj是一个对象 prop也是一个对象
1.2 是obj里面的prop这个属性调用了getFullName,本质就是prop调用了getFullName
1.3 注意,prop的值本身就是一个对象,这个对象调用了方法,方法里面的this指向prop
1.4 而prop里面并没有getFullName,就会打印undefined
1.5 为什么不是报错?注意,如果对象里面没有这个值,强行打印就是undefined
var o = {
name: 'jmq'
}
console.log(o.name1); // undefined
2. 为什么第二个地方是language?
因为这里打印language是因为test是在全局下执行
例题8:
HTML:
<input type="button" value="点击按钮1" onclick="fun()">
JavaScript:
<script>
function fun() {
console.log(this);
}
</script>
这里特别记住,打印出来是window,写在html标签里面的onclick事件,虽然是点击事件,但是这里的fun()函数要理解为是window内置的,
类比:
alert()也是window内置的方法
<input type="button" value="点击按钮2" onclick="alert()">
例题9:
HTML:
<input type="button" value="按钮3" id="btn3">
JavaScript:
var btn3 = document.querySelector("#btn3");
btn3.onclick = fun1;
function fun1() {
console.log(this);// 打印什么
}
打印出来是按钮对象。为什么是按钮,不是window?
可以理解为btn3是一个DOM对象,onclick是对象里面的一个方法,执行的函数体就是fun1里面的内容,==>最终是按钮这个对象调用了方法,所以this指向按钮
例题10:
HTML:
<button id="btn">点击按钮</button>
JavaScript:
问,点击按钮,最终输出什么?undefined?data里面的索引为1的数据?还是……
var userInfo = {
data: [
{ "username": "jmq", "id": 19 },
{ "username": "syc", "id": 20 }
],
getuserInfo: function () {
var index = 1;
console.log(this.data[index].username + ":" + this.data[index].id);
}
}
var btn = document.querySelector("#btn");
// 问,点击按钮,最终输出什么?undefined?data里面的索引为1的数据?还是……
btn.onclick = userInfo.getuserInfo;
最终是报错,为什么报错?
原因是:
1.按钮点击,即便为userInfo这个对象调用本身的方法,this指向的依旧是按钮这个对象,所以按钮不存在data这个属性。按钮不存在这个属性,强行打印,就会报错
2. 上面的代码可以改成如下
btn.onclick = function () {
var index = 1;
console.log(this.data[index].username + ":" + this.data[index].id);
}
如果代码改成这样调用,
var userInfo = {
data: [
{ "username": "jmq", "id": 19 },
{ "username": "syc", "id": 20 }
],
getuserInfo: function () {
var index = 1;
console.log(this.data[index].username + ":" + this.data[index].id);
}
}
userInfo.getuserInfo(); // 打印的是 syc:20 不会调用
代码修改前,如何实现,按钮点击,能够不报错成功打印,可以利用bind
备注:
bind和call的相同点和不同点:
相同点:1. 都可以调用函数 2. 都可以改变this的指向 3. 返回的是一个新的函数
不同点:bind是想指定啥时候调用就啥时候调用,call是立即马上执行函数
var userInfo = {
data: [
{ "username": "jmq", "id": 19 },
{ "username": "syc", "id": 20 }
],
getuserInfo: function () {
var index = 1;
console.log(this.data[index].username + ":" + this.data[index].id);
}
}
btn.onclick = userInfo.getuserInfo.bind(userInfo); // 这里修改了,能够点击打印数据,不会报错
例题11:定时器指向
function fn() {
console.log(this);
}
setInterval(fn, 1000); // 这里打印啥?
不管是setInterval还是setTimeout这里打印的都是window,
怎么理解?上面的定时器可以写成window.setInterval(fn, 1000); 可以把定时器理解为window的一个函数,就是window调用了定时器,进而里面的函数fn也是window调用的
例题12:定时器this特殊情况【据说面试可能会有】
var k = {
a: 1,
sing: function () {
console.log(this);
}
}
setTimeout("k.sing()", 1000); // 这里打印的是啥?
打印的是object对象。为什么?
首先来思考,一般定时器的第一个参数是函数,但是其实也可以放一个执行体,比如
setTimeout("console.log('aa')", 1000);
进一步来思考,最上面的k.sing() 调用,因为是k对象调用了sing方法,即便是定时器setTimeout作为window的全局对象,此时this也是指向obj对象,这里可以这样理解,也可以记住
例题13:bind call apply的this指向
var btn = document.querySelector("#btn");
function smell() {
var a = 10;
console.log(this.a);
}
var o = {
a: 100,
smell: function () {
console.log(this.a);
}
}
smell.call(o); // 打印什么
btn.onclick = smell.bind(o); // 打印什么
smell.apply(o); // 打印什么
第一个,立即打印100,
第二个,点击后打印100,
第三个,立即打印100
上面三个,都是通过方法,改变this的指向,this都指向o,所以打印的是o里面的a变量,都是100,只是执行函数的时间点的差别。
注意,bind是可以指定啥时候触发函数。apply和call都是立即执行这个函数。apply第二个参数是必须传递数组,call和bind第二个参数不是数组。【这里我有点忘啦,有待补充】
问题14:this与箭头函数
this总是指向函数的调用者?不一定, 箭头函数的this指向window
var value = 8;
var obj = {
value: 10,
fn: () => {
console.log(this.value); // 打印的是8
}
}
obj.fn();
发现fn这个方法是obj对象调用的,但是this指向window不指向obj;同理,this也不总是指向触发这个事件的对象
箭头函数中this 指向父级的上下文中的this,是定义的时候就确定的。
且,不可以被call apply bind改变
const zhangsan2 = {
name: '张三',
sayHi() {
console.log(this);
},
waitAgain() {
setTimeout(() => {
// this指向 当前对象
console.log(this);
})
}
}
zhangsan2.waitAgain()
// 箭头函数 this指向 当前函数所在父级的上下文对象
// 当前函数的父级是waitAgain函数 上下文是在zhangsan2这个对象
上面的箭头函数是一个waitAgain函数,waitAgain函数的上下文对象是zhangsan2,因此指向zhangsan2
问题15: this总是指向事件的触发者还是事件的绑定者?触发者和绑定者不一样时?
事件委托【事件委派】时,
var ul = document.querySelector("ul");
var lis = ul.querySelectorAll("li");
ul.addEventListener("click", function () {
console.log(1);
console.log(this); // 当点击小li,打印时,this指向ul,指向事件的绑定者,而不是触发者
})
结尾:
学习id: 201903090124-29
现在是大三学生,学习到了前后端交互阶段,如有不对的地方,欢迎指正,一起努力呀。如有转载请注明出处。