一、什么是this?
定义:this解析器在调用函数时传递给函数的一个参数,this指向的是一个对象,这个对象我们称为函数指向的上下文对象,根据函数的调用方式不同(跟创建方式无关),this会指向不同的对象。
二、this的指向
- 函数的不同调用方式决定了this 的指向不同
1、普通函数
function foo(){
console.log(this);//Window
}
foo();
结论:普通函数中this指向window
2、对象
var o = {
sayHi: function() {
console.log(this);
}
}
o.sayHi();
结论:对象中 this指向的是对象 o
3、构造函数
function Animal(type, name, color, eat) {
console.log(this);
this.type = type;
this.name = name;
this.color = color;
this.eat = eat;
this.do = function() {
}
}
var dog = new Animal('哺乳动物', '狗', '黑色', function() {
console.log('喜欢吃骨头')
});
var fash = new Animal('水生动物', '猫', '黑白色', function() {
console.log('喜欢吃虾米')
});
console.log(dog);
console.log(fash);
dog.eat();
fash.eat();
dog.do();
fash.do();
总结:构造函数中this指向的是构造函数(new)所创建的对象
4、绑定事件函数
<body>
<button class="btn">点击按钮</button>
<script>
var btn = document.querySelector('.btn');
btn.onclick = function(){
console.log(this);
}
</script>
</body>
总结:绑定事件函数中this的指向:[触发事件的元素],不是绑定事件的元素
5、定时器函数
window.setTimeout(function() {
console.log(this);
}, 1000);
总结: 定时器函数中this的指向的是window
6、立即执行函数
(function() {
console.log(this);
})();
总结:立即执行函数中this的指向是window
三、this的原理
- 原理一:
[与函数调用结合]:
当一个函数在执行的时候,就会创建一个上下文对象,[会产生局部作用域],上下文对象中,函数是被谁调用,在哪里调用的,参数是什么等信息;this就是记录的一个属性,在函数被调用时产生。 - 原理二:
[结合作用域看this]:
问题:为什么return返回为对象、数组、函数。this就不指向实例化的对象;函数本身不能作为构造函数,new类似失效。创建一个对象,就是将构造函数的作用域赋给了新对象;所以this 指向了这个对象,return {}, [],function 之后;改变了作用域,作用域赋值给了 {}、function、[] ,所以this指向{}、[]、function。
四、改变this的指向
1、call
<script>
var name = '周超';
function foo() {
console.log(arguments);
var name = '刘玉才';
console.log(this.name);
}
var wjh = {
name: '网鱼行',
foo: foo
}
var fei = {
name: "宇飞",
foo: foo,
cname: this.name
}
var yuAng = {
name: '虞昂',
foo: foo
}
foo();
wjh.foo();
fei.foo();
//call() 改变funcion函数中this 指指向,触发函数
// 参一指定this 指向的对象
// 参二参N: 给调用函数 foo 传入实参
foo.call(fei,'我就是我,一个独立花朵',12);
foo();
</script>
2、apply
<script>
var name = '周超';
function foo() {
console.log(arguments);
var name = '刘玉才';
console.log(this.name);
}
var wjh = {
name: '王雨行',
foo: foo
}
var fei = {
name: "宇飞",
foo: foo,
cname: this.name
}
var yuAng = {
name: '虞昂',
foo: foo
}
// apply:改变funcion函数中this 指指向,触发函数
// 参一:指定this 指向的对象
// 参二:为数组;作用:调用函数传入的实参
yuAng.foo.apply(window,[1,2,43,4]);
</script>
3、bind
<script>
var name = '周超';
function foo() {
console.log(arguments);
var name = '刘玉才';
console.log(this.name);
}
var wjh = {
name: '王雨行',
foo: foo
}
var fei = {
name: "宇飞",
foo: foo,
cname: this.name
}
var yuAng = {
name: '虞昂',
foo: foo
}
// bind: 改变funcion函数中this 指指向, 加上执行符 才能触发函数
// 参数:指定this 指向的对象
yuAng.foo.bind(window)('1', 2, 3)
</script>
五、如何判断this的指向?
如何判断this指向?
1、this在那个作用域中
- 全局:this指向的是window
- function 函数体中
2、函数执行
- 看是否有call apply bind,若有。参数一是谁,this的指向就是谁。
- 看是否是事件绑定函数,若是。this的指向就是触发事件的元素。
- 调用函数是否是new,若是构造函数。this的指向是new实例化的对象。
- 若以上都不满足,通用规律,谁调用它this的指向就是谁。
小示例
var name = '滚滚滚';
var obj = {
name: '于飞',
cname: this.name,
say: function() {
console.log(`${this.name}说'于飞好帅呀!!!'`);
}
}
/*obj.say();*/
var say = obj.say;
say(); //window.say 滚滚滚说'于飞好帅呀!!!
var lzr = {
name: '李宗仁',
say: function() {
console.log(`${this.name}说:我长得好帅呀`);
}
}
lzr.say.call(obj); //于飞说:我长得好帅呀
lzr.say.apply(this); //滚滚滚说:我长得好帅呀