this是在什么时候确定下来的?
首先必须要说的是,this和作用域不一样,作用域是声明的时候就确定下来的,而this指向是在函数执行的时候才能确定是谁,this的指向最终指向那个调用它的对象。
例子1
function a(){
var user = "qm";
console.log(this.user); //undefined
console.log(this); //Window 严格模式下是undefined
}
a();
a是全局函数,this指向是window,严格模式下是undefined
例子2
setTimeout(function () {
console.log(this); //window setTimeout比较奇怪,默认绑定严格模式下竟然不是undefined
});
btn.onclick = function(){ // 这是一个函数A
setTimeout(function(){ // 这是一个函数B
console.log(this); //window
},0)
}
btn.onclick();
对于setTimeout是一个特例,this指向指向window
例子3
var o = {
user:"qm,
fn:function(){
console.log(this.user); //qm
console.log(this) // o
}
}
o.fn();
这里的this指向是对象o,因为你调用fn对通过o.fn()执行的,那自然指向是对象o。再次强调一下,this的指向只有调用的时候才能决定,谁调用就指向谁。
例子4
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12
console.log(this); // b
}
}
}
o.b.fn();
var o = {
a:10,
b:{
// a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); // b
}
}
}
o.b.fn();
就算对象嵌套多层,this指向也是他上一级对象,因为是b对象调用的,所以this指向指向b
例子5
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); //window
}
}
}
var j = o.b.fn;
j();
这里指向还是window,是不是有些懵逼?其实是因为没有理解一句话
this永远指向的是最后调用它的对象,也就是看它执行的时候谁调用的,这是是把变量赋值给了j,最后执行的是j,所以最后this指向是window
例子6
const obj1 = {
name:'joy',
getName(){
console.log(this); //obj
console.log(this.name); //joy
}
};
const obj2 = {
name:'sam',
friend:obj1
};
const obj3 = {
name: 'jam',
friend:obj2
};
obj3.friend.friend.getName() //obj joy本质上还是obj1调用的
const obj1 = {
name:'joy',
getName(){
console.log(this);
console.log(this.name);
}
};
const obj2 = {
name:'sam',
getName:obj1.getName
};
obj2.getName() //obj2 sam
这是一些链式调用
例子7 (构造函数版this)
function Fn(){
this.user = "qm";
console.log(this) // 此处this 分别指向Fn的实例对象a1 a2
}
var a1= new Fn();
var a2=new Fn();
console.log(a.user); //qm
当this碰到return时
function Fn()
{
this.user = 'qm';
return {};
}
var a = new Fn();
console.log(a.user); //undefined
再看一个
function Fn()
{
this.user = 'qm';
return function(){};
}
var a = new Fn();
console.log(a.user); //undefined
再来
function Fn()
{
this.user = 'qm';
return 1;
}
var a = new Fn();
console.log(a.user); //qm
function Fn()
{
this.user = 'qm';
return undefined;
}
var a = new Fn();
console.log(a.user); //qm
什么意思呢?
如果返回值是一个对象,那么this指向就是那个返回的对象,如果返回值不是一个对象,那么this还是指向函数的实例
再看
function Fn()
{
this.user = 'qm';
return undefined;
}
var a = new Fn();
console.log(a); //fn {user: "qm}
还有一点就是null也是对象,但是在这里this指向还是函数实例,因为null比较特殊
function Fn()
{
this.user = 'qm';
return null;
}
var a = new Fn();
console.log(a.user); //qm
new的原理,就是新建一个对象实例,this指向这个空对象,执行构造函数方法,属性和方法被添加到this引用的对象中
例子8
<body>
<button id="btn">hh</button>
<script>
var oBtn = document.getElementById("btn");
oBtn.onclick = function() {
console.log(this); // btn
}
</script>
</body>
通过绑定事件的方法,此时this指向绑定事件的对象
例子9(想要改变setTimeout的this指向)
btn.onclick = function(){
var self = this; //使用变量保存this
function fn(){ //将代码写在一个函数fn中
console.log(this);
}
setTimeout(function(){
fn.call(self); //强行指定this为self对象
},0)
}
btn.onclick();
/*
call方法的作用,是调用函数,同时指定this可以代表谁
例如 fn.call(obj)
意思就是 调用函数fn,并且this指向obj对象
*/
btn.onclick = function(){
var self = this; //使用变量保存this
function fn(){ //将代码写在一个函数fn中
console.log(this);
}
setTimeout(function(){
fn.apply(self); //使用apply方法调用函数,强行指定this为self对象
},0)
}
btn.onclick();
/*
apply方法的作用,是调用函数,同时指定this可以代表谁
例如 fn.apply(obj)
意思就是 调用函数fn,并且this指向obj对象
*/
btn.onclick = function(){
setTimeout(function(){
console.log(this);
}.bind(this), 0 )
//使用bind方法,将定时器函数的this强行绑定为事件函数的this
}
btn.onclick();
/*
bind方法的作用,是绑定函数的this,同时返回绑定后的新函数
例如
var fb = fn.bind(obj);
window.fb();
无论谁调用fb函数, 函数的this都会指向obj
*/
利用call,apply,bind改变this指向
如何判断箭头函数的this?
因为箭头函数不具备自己的this,所以非常简单,只要假装它不存在,就想这样,这下this指向就很清晰了
2.箭头函数可以用call来改变this指向吗?
不能!!试图改变箭头函数的this是徒劳的