什么是this
- this是Javascript语言的一个关键字
- 它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。
- 随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象
this的多种用法
全局范围内
函数调用
作为对象方法的调用
call/apply/bind 的调用
作为构造函数调用
全局范围内使用this
在全局范围内使用this ,它将指向全局对象(浏览器中为 window)
var name = 'name1';
console.log(name);
this.name = 'name2';
console.log(name);
console.log(this.name);
window.name = 'name3';
console.log(name);
console.log(this.name);
console.log(window.name);
纯粹的函数调用
这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global
// 案例1
function test(){
this.x = 1;
alert(this.x);
}
test(); // 1
// 案例2
var x = 1;
function test(){
alert(this.x);
}
test(); // 1
// 案例3
var x = 1;
function test(){
this.x = 0;
}
test();
alert(x); //0
在事件中表示当前元素的时候,可以使用this
var btn = document.getElementById("btn");
btn.onclick = function() {
this.value = "按鈕"; //给btn注册的事件,因此this表示btn
}
在html结构中的this,指向的绑定事件的元素本身
<button onclick = "fun(this)">
点击
</button>
<script>
function fun(_this){
console.log(_this); // 当前元素
}
</script>
对象中的this
字面量对象中的this:指的就是对象本身
var obj = {
name:'jack',
say:function(){
console.log('obj中的this',this.name);
}
}
obj.say()
定时器中的this
<style>
#box1{
width: 200px;
height: 200px;
border: 1px solid #f00;
}
</style>
<body>
<div id="box1"></div>
<script>
var str = '每一种食物,都是大自然的馈赠,也离不开姐姐的栽培。看着这一片绿油油的蔬菜,真的很令人羡慕,也有不少网友评论:这就是最好的生活。';
box1.onclick = function(){
var num = 0;
setInterval(function(){
num++;
box1.innerHTML = str.substring(0,num);
// 在定时器中的this是window,因为setInterval,其实是window.setInterval()
this.innerHTML = str.substring(0,num);
},100);
}
// 解决方案一:自定义一个变量_self来存储this
box1.onclick = function(){
var _this = this; // 把this对象对应的地址存储到_this中
var num = 0;
setInterval(function(){
num++;
box1.innerHTML = str.substring(0,num);
_this.innerHTML = str.substring(0,num);
},100);
}
// 解决方案二:使用箭头函数来解决
// 箭头函数是函数表达式的简略的写法
// 箭头函数中是没有this指向的,箭头中的函数指向是由定义他的作用域来决定this是谁(谁定义了箭头函数,this是谁)
box1.onclick = function(){
// 箭头函数是在这个事件监听函数中被定义出来的,所以箭头函数中的this,就是事件监听的this
var num = 0;
setInterval(()=>{
num++;
box1.innerHTML = str.substring(0,num);
this.innerHTML = str.substring(0,num);
},100);
}
</script>
箭头函数中的this
箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值,自己本身并没有this值;
箭头函数的this永远指向其上下文的this,任何方法都改变不了其指向,如call(), bind(), apply()。
call和apply中的this
call和apply 中的this指的是当前元素本身,传递进去之后,会修改方法里面的this指向
总结:非箭头函数情况下,分为两种情况:
1.this指向调用函数或者变量的对象(并且采取就近原则)
2.定时器的this永远指向window,除非使用bind等函数人为的改变指向
call(),apply(),bind() 方法
所有函数都是对象,都有call(),apply(),bind()方法,都是为了改变this指向
call方法
语法格式:fun.call(this,obj1,obj2);
JS中充满了各种各样的简写,其实这个调用也是一个简写 思考:默认情况下fun中的this指向哪里
function fun(){
console.log(this);
}
box1.onclick = function(){
fun();
}
思考:如何将fun中的this改变为box1?
function fun(){
console.log(this);
}
box1.onclick = function(){
fun.call(this); // 使用call,修改this指向
}
如果想要传递参数,可以写在this的后面
function fun2(a,b){
console.log(a+b);
console.log(this);
}
box1.onclick = function(){
fun2.call(this,10,20)
}
案例:页面中有两个div容器,点击容器的时候,分别渲染进去不同的内容
<style>
div{
width: 200px;
height: 200px;
border: 1px solid #f00;
}
</style>
<div id="box1"></div>
<div id="box2"></div>
<script>
var data1 = ['red','blue','green'];
var data2 = ['apple','banana','orange'];
function render(data){
var html = '<ul>';
for(var i=0;i<3;i++){
html += "<li>"+data[i]+"</li>";
}
html += "</ul>";
this.innerHTML = html;
}
box1.onclick = function(){
render(data1); // 不能显示
render.call(this,data1);
}
box2.onclick = function(){
render(data2); // 不能显示
render.call(this,data2);
}
</script>
apply方法
call和apply相似,不同指出在于传递的方式不同,call的参数需要逐个列举,apply的参数需要通过数组的形式传递
语法格式:fun.apply(this,[obj1,obj2]);
function fun(){
console.log(this);
}
function fun2(a,b){
console.log(a+b);
console.log(this);
}
box1.onclick = function(){
fun.apply(this)
fun2.apply(this,[10,20])
}
apply虽然传递的是数组,但是接收的时候还是一个个接收的,所以10和20会分别被传递给a和b
案例:思考,如何在数组中获取数组中的最大值
var arr = [56,76,45,34,87,98];
var max = Math.max(arr); // 不能使用
var max = Math.max(arr[0],arr[1],arr[2]); // 可以使用,太麻烦
var max = Math.max.apply(null,arr); // 最优解
var max = Math.max(...arr); // 最优解
console.log(max);
bind方法
bind有两个特点
不会调用函数
可以改变函数内部this指向
bind()方法不会调用函数,但是能改变函数内部this指向
语法格式:Fun.bind(this,arg1,arg2);
案例一:改变fun中的this指向
function fun() {
console.log(this);
}
box1.onclick = function () {
// 把当前事件中的this指向传递给fun函数
var aa = fun.bind(this);
aa();
}
带参数的bind调用
function fun2(a, b) {
console.log(a + b);
console.log(this);
}
box1.onclick = function () {
// bind传參的格式和call是一样的,直接用逗号隔开
var aa = fun2.bind(this,10,20)
aa();
}
思考:将fun函数中的this,修改为Obj对象
var Obj = {
name:'jack',
age:18
}
function fun() {
console.log(this);
}
// 把fun中的this指向,只想到Obj身上
var newFun = fun.bind(Obj);
newFun(); // 这时候fun中的this,就变成了obj
注意:bind虽然可以改变this指向,但是不会自动调用,需要手动添加调用方式
面试题call,apply,bind有什么区别:call 和 apply 特性一样
都是用来调用函数,而且是立即调用
但是可以在调用函数的同时,通过第一个参数指定函数内部 this 的指向 call 调用的时候,参数必须以参数列表的形式进行传递,也就是以逗号分隔的方式依次传递即可 apply 调用的时候,参数必须是一个数组,然后在执行的时候,会将数组内部的元素一个一个拿出来,与形参一一对应进行传递 如果第一个参数指定了 null 或者 undefined 则内部 this 指向 window
bind可以用来指定内部 this 的指向,然后生成一个改变了 this 指向的新的函数
它和 call、apply 最大的区别是:bind 不会自动调用