1.不在函数中的this指向?
浏览器环境就是指向全局对象window
node环境中是指向一个空对象
2.函数中的this
取决于如何调用这个函数:创建执行上下文的时候确定了这次函数调用的this指向。
| 调用方式 | 示例 | 函数中的this指向 |
|---|---|---|
| 通过new调用 | new method() | 新对象 |
| 直接调用 | method() | 全局对象 |
| 通过对象调用 | obj.method() | 前面的对象 |
| call/apply/bind | method.call(ctx) | 第一个参数 |
1. 通过new调用
function Person(name,age){
this.name = name;
this.age = age;
this.say = function(){
console.log(this); //指向的是通过这个构造函数创建的实例对象
}
}
let p1 = new Person("小明",25);
p1.say();
2.直接调用
// 情况1
function test(){
console.log(this); // this指向window
}
test();
// 情况2
var prop = 20;
let obj ={
prop:1,
print: function(){
console.log(this); // this指向的是obj对象(通过对象调用)
function test(){
console.log(this); // this指向window(函数直接调用)
};
test()
}
}
obj.print();
// 情况3:立即调用函数
(function(){
console.log(this); //window
})()
3.通过对象调用
// 情况1
function print(){
console.log(this.prop); // this指向的是obj对象,所以输出1
}
var prop = 20;
let obj ={
prop:1,
}
obj.print = print;
obj.print();
// 情况2
var prop = 20;
let obj ={
prop:1,
print: function(){
console.log(this.prop); // this指向的是obj对象,所以输出1
}
}
obj.print();
// 情况3,多层嵌套对象的this指向
var prop = 20;
let obj ={
prop:1,
b: {
prop:5,
print: function(){
console.log(this); // this指向的就是obj.b,输出5
}
}
}
obj.b.print();
所以通过对象调用普通函数(非箭头函数),method中的指向,谁调用,这个this就指向谁。
4.call/apply/bind调用
- call/apply:用来设置调用函数时函数体内的this对象的值。(改变函数的this指向)
apply("函数内this的指向","参数数组") call("函数内this的指向",参数1,参数2...)
//案例1
function fun() {
console.log(this.name)
}
let cat = {
name:"喵喵"
}
fun(); //this指向的是window,直接调用函数。window的name不设置就会返回"",若是其他不存的属性就返回undefined
fun.apply(cat); //此时通过apply改变了fun中的this指向,现在指向是cat,所以输出的是喵喵
// 案例2,传参
let cat = {
name:"喵喵",
}
let dog = {
name:"旺旺",
eat(food1,food2){
console.log("我喜欢吃"+food1+"和"+food2,this)
}
}
dog.eat("肉","骨头"); // 输出“我喜欢吃肉和骨头”,this指向dog
dog.eat.apply(cat,["鱼","肉"]); // 输出“我喜欢吃鱼和肉”,this指向cat
dog.eat.call(cat,"鱼","肉"); // 输出“我喜欢吃鱼和肉”,this指向cat
// 这里也能看出来call和apply的区别就是传参的方式,call参数是一个个传,apply是通过数组的方式传。
- bind:创建一个新的函数实例,this值会绑定到传给bind()的对象
bind("函数内this的指向",参数1,参数2...)
let cat = {
name:"喵喵",
}
let dog = {
name:"旺旺",
eat(food1,food2){
console.log("我喜欢吃"+food1+"和"+food2,this)
}
}
dog.eat.bind(cat,"鱼","肉"); // 这里不会输出,因为bind是返回的新的函数实例
let catEat = dog.eat.bind(cat,"鱼","肉");
catEat(); // 输出“我喜欢吃鱼和肉”,this指向cat
3.setTimeout和setInterval中this的指向
var prop = 20;
let obj ={
prop:1,
show(){
console.log(this,this.prop);
// 对象调用,所以this是obj,prop是1
setTimeout(function(){
console.log(this,this.prop);
// 这里setTimeout是window方法,所以指向是window
},500)
}
}
obj.show();
4.箭头函数的this指向
箭头函数的 this 指向的是定义箭头函数的上下文。
箭头函数的 this 是在创建它时外层 this 的指向。
箭头函数不绑定this,而是从定义它的作用域中继承this值,所 以call/apply/bind方法对它的this毫无影响。
- 箭头函数定义的上下文是window,所以this的指向是window
var prop = 20;
const say = () =>{
prop:22;
console.log(this); // 指向window
console.log(this.prop) //输出20
}
say();
- 当箭头函数作为一个对象的方法的时候,并不会把this绑定到该对象上,而是继承了上一级作用域中的this值。
var prop=11;
var obj={
prop:22,
say:()=>{
console.log(this.prop); //指向window,输出11
}
}
obj.say();//输出的值为11.
- setTimeout和setInterval中使用箭头函数的this指向不一定是window,而是继承上下文的this指向。
var prop = 20;
let obj ={
prop:1,
show(){
console.log(this,this.prop);
// 对象调用,所以this是obj,prop是1
setTimeout(()=>{
console.log(this,this.prop);
// 这里setTimeout是window方法,但是箭头函数会继承定义该函数上下文的this指向,这里的this指向是obj。
},500)
}
}
obj.show();