文章目录
前言
初学JavaScript
时,当学到this
这个关键字时,傻傻分不清楚this
指向的究竟时哪个对象,本文就对其进行介绍。
1.作为对象的方法调用
当函数作为对象内的方法进行调用时,this
指向调用的对象
let obj = {
say: "喵喵喵",
sayHi: function() {
console.log(this.say);
}
}
obj.sayHi(); //喵喵喵
2.作为普通函数调用
当函数作为一个普通方法进行调用时,this
指向的是全局对象,在浏览器中,指向的Window
对象
window.name = '提灯寻猫';
function myname() {
console.log(this.name);
}
myname();
注意: 如果用node运行js文件,会报错,所以还是要用html的方式,这里的this.name
指向全局中的name
3.作为构造函数调用
通常的说就是用new
关键字返回一个对象,this
通常也指向这个对象。
let MyName = function() {
this.name = '提灯寻猫';
}
let obj = new MyName();
console.log(obj.name);
迷惑性代码:
let MyName = function() {
this.name = 1;
return {
name: 2
}
}
let obj = new MyName();
console.log(obj.name);
这里有的小伙伴就会问为什么输入的obj.name
的值是2?这是因为我们显式的返回一个对象,通过new
得到的也就是显式返回的那个对象,即{name:2}
4.call或apply调用
call
和apply
相对于普通函数的调用,他们可以动态的改变this
的指向,我们在使用继承时也会经常使用到他们,十分重要。
4.1call和apply的区别
从本质上讲他们没有太大的区别,唯一的区别就是传入的参数不同.
call 和 apply 的第一个参数即指定函数体内的this指向
call 的第二个参数为一个数组或者伪数组
apply 的第二个参数为一个不定参数,可以是一个也可以是多个
4.2使用call实现继承
使用call
和 apply
都可以实现继承,这里就用call
进行演示
function Goods(name, price) {
this.name = name;
this.price = price;
}
function Bag(name, price) {
Goods.call(this, name, price);
this.say = "太贵了,买不起"
}
let bag1 = new Bag('lv', 30000);
console.log(bag1);
说明 Goods.call(this,name,price)
,即在Bag
这个作用域调用了Goods
中的方法
4.3调用函数并指定上下文
obj
即调用的this
function showName() {
console.log(`姓名:${this.name},密码:${this.password}`);
};
var obj = {
id: 1,
name: '提灯寻猫',
password: "123456"
};
showName.call(obj)
4.4单纯调用apply
let max = Math.max.apply(null, [1, 2, 3, 4, 5]);
console.log(max);// 5
5.箭头函数
箭头函数不会创建自己的this
,他只会从自己作用域链的上一层继承this
this.num = 2;
let obj = {
num: 1,
getNum: () => {
console.log(this.num);
}
}
obj.getNum();
这里的obj.getNum()
中所指的this
,并非指向调用者本身,而是指向外部,若外部没有相对应的值,则是undefined
6.小试牛刀
题目一
function a() {
function b() {
console.log(this); //window
function c() {
"use strict"
console.log(this); //undefined
}
c();
}
b();
}
a();
函数b作为一个普通函数调用,所以其中的this
指向全局,所以打印出的Window
对象,函数c打印出undefined
的原因即使用了严格模式,在严格模式下,this
的值为undefined
题目二
let name = '孙悟空';
function sayName() {
console.log("姓名" + this.name);
}
let person = {
name: '孙悟饭',
detail: function() {
console.log("姓名" + this.name);
},
freeman: {
name: '比克',
detail: function() {
console.log("姓名" + this.name);
}
},
sayName: sayName
}
person.detail(); //孙悟饭
person.freeman.detail(); //比克
person.sayName(); //孙悟饭
person.detail()
调用person
对象中的方法,person.freeman.detail()
调用person.freeman
这个对象,person.sayName()
看上去是作为一个普通函数调用,实际上是person
这个对象进行调用全局的sayName
方法。
题目三
window.name = '孙悟空';
function sayName() {
let name = '比克';
console.log("姓名" + this.name);
}
function d(i) {
return i();
}
let person = {
name: '孙悟饭',
detail: function() {
console.log("姓名" + this.name);
},
freeman: function() {
return function() {
console.log(this.name);
}
},
}
let c = person.detail;
person.sayName = sayName; //相当于给person添加了sayName方法
let e = person.freeman();
sayName(); //孙悟空 //调用全局
c(); //孙悟空 //相当于普通函数
person.sayName(); //孙悟饭
d(person.detail); //孙悟空 //相当于函数调用
e(); //孙悟空 //虽然是个闭包,但还是相当于函数调用
本文到这里就结束了,如果觉得文章不错,不妨点赞、评论一下吧!