1.javaScript语言精粹
中分四类场景
- 有对象就指向调用对象(箭头函数除外,箭头函数没有独立的this作用域,所以往外层走)
var myObject = {value: 2017};
myObject.getValue = function(){
console.log(this.value); //2017
console.log(this); //{value: 2017,[Function]}
return this.value;
};
console.log(myObject.getValue); //2017
var a = {
name: js;
getName:function(){
console.log(this);//a对象
setTimeout(()=> {
console.log(this);//a对象
},0)
}
}
- 没调用对象就指向全局对象
var myObject = {value: 2017};
myObject.getValue = function(){
var f = function(){
console.log(this.value); //undefined
console.log(this); //输出全局对象
};
f();
return this.value;
};
console.log(myObject.getValue); //2017
f函数虽然定义在getValue函数体内,但实际上不属于getValue也不属于myObject,没绑定到任何对象上,所有当调用this
指向全局变量
- 用new
构造就指向新的对象
JS中通过new
关键字调用构造函数,this
绑定新的对象
var F = function(){
this.value = 2017;
}
var myObject = new F();
console.log(myObject.value); //2017
- 通过
apply
或call
或bind
来改变this
的指向
apply()方法接收两个参数,第一个函数运行的作用域,另一个是参数数组(arguments)
call()方法第一个参数和apply()方法相同,只是其他的参数需要一一列出来
var myObject = {value: 2017};
var f = function(){
console.log(this);
};
f(); //全局变量
f.apply(myObject); //{value: 2017}
f.call(myObject); //{value: 2017}
var newF = f.bind(myObject);
newF(); //{value: 2017}
2.普通函数,对象函数,定时器,构造函数,事件函数,call()/apply()
1.普通函数
var name = "js";
function demo(){
var name = 'css';//在函数内部定义并声明的变量是局部变量
console.log(this.name); //js
}
demo(); //window.demo(),只不过我们在平常写代码的时候会自动忽略掉。
//所以window是函数的调用者,this指向window,this下name属性的值就是全局变量
//所以输出的是全局变量 js,而不是局部变量 css
2.定时器
1.
setInterval(function(){
var a = 2017;
alert(this.a);
},1000); //undefined,setInterval方法也属于window,因为window对象下没有a属性,因此浏览器每隔一秒弹出一次undefined提示框
2.
function Demo(){
this.a = 2017;
setInterval(this.show,1000);
}
Demo.prototype.show = function(){
alert(this.a);
}
var demo = new Demo();
demo.show(); //第一次弹出2017,之后每一秒弹出undefined
//原因在this.show代表了Demo.prototype.show的函数体,this指向Demo,所以第一次弹出2017;
//之后延迟定时器开始工作,定时器时钟到达之后this指向window,window下没有a属性,所以每隔一秒弹出undefined
3.对象方法
var myObject = {
name: "js",
f: function(){
alert(this.name);
}
}
var demo = myObject.f();
demo(); //js,如果一个对象中的方法有this,上一级调用这个方法,this指向上一级对象
4.构造函数
function Person(name,age){
this.name = name;
this.age = age;
function f(){
alert('JavaScript');
}
// return f;
}
var per = new Person('js',2017);
console.log(per); //new关键字在内存中开辟了新的内存空间,返回首地址的值,并将this指向开辟的内存空间上,输入per对象,如果取消return注释,输出f函数体
5.事件函数
<body>
<button id='btn'>Click</button>
</body>
<script type="text/javascript">
var btn = document.querySelector('#btn');
btn.onclick = function(){
function fn(){
alert(this); //弹出window,如果事件函数中还有其他的函数,this还是指向window
}
fn();
}
</script>
如果想修改this的指向,可以用以下两种方法
在onclick函数中将this指针赋值给一个变量var _this = this; 然后fn()函数调用_this变量就可以指向button对象了
将下面执行的fn函数改为fn.call(this);
来改变this指向 apply函数类似
总结:
1. 构造函数中this
就是即将new
出来的对象
2. 全局普通函数this
指向全局变量window
3. 函数作为对象的一个属性,并且作为对象的一个属性被调用(obj.fn();),this
指向该对象(带括号就是对函数的调用,得到返回值)
4. 属性函数被赋值给另一个变量,并没有作为一个属性被调用,this
指向windos
就像var fn1 = obj.fn; fn1();
只是一个引用,对象到fn1了成全局的
5. 在对象函数属性中还有函数时,这个函数就是一个普通函数,this
指向window
还可以参考判断最简单的JS中this的指向