总结
1.浏览器里,在全局范围内的this 指向window对象;
2.在函数中,this永远指向最后调用他的那个对象;
3.构造函数中,this指向new出来的那个新的对象;
4.Call、apply、bind中的this被强绑定在指定的那个对象上;
5.箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
6.apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。
前言
在讲this之前,先得说说 环境 这个概念。一门语言在运行的时候,需要一个环境,叫做宿主环境。对于JavaScript,宿主环境最常见的是web浏览器,另一个最为常见的就是 Node 了,同样作为宿主环境,node 也有自己的 JavaScript 引擎:V8(目前最快JavaScript引擎、Google生产)
this的初衷
this设计的初衷是在函数内部使用,用来指代当前的运行环境。为什么这么说呢?
JavaScript中的对象的赋值行为是将地址赋给一个变量,引擎在读取变量的时候其实就是要了个地址然后再从原始地址中读取对象。而JavaScript 允许函数体内部引用当前环境的其他变量,而这个变量是由运行环境提供的。由于函数又可以在不同的运行环境执行(如全局作用域内执行,对象内执行…),所以需要一个机制来表明代码到底在哪里执行!于是this出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
全局中的this:
在浏览器和全局中
this就相当于window对象
如果不使用 var const let 去声明一个对象就相当于给win声明了一个对象 因为是全局的
this就是老大,因为是全局 this指向老大win 所你无论声明什么this都指向什么
// 1
console.log(this === window); //true
//2
var name = "Jake";
console.log(this.name ); // "Jake"
console.log(window.name ); // "Jake"
//3
age = 23;
function testThis() {
age = 18;
}
console.log(this.age ); // 23
testThis();
console.log(this.age ); // 18
函数中的 this:
没调用前还是win
this永远指向最后调用它的那个对象。
var name = "windowsName";
function sayName() {
var name = "Jake";
console.log(this.name); // windowsName
console.log(this); // Window
}
sayName();
console.log(this) // Window
function foo() {
console.log( this.age );
}
var obj1 = {
age : 23,
foo: foo
};
var obj2 = {
age : 18,
obj1: obj1
};
obj2.obj1.foo(); // 23
构造函数中的this:
new的是那个,this就指向那个
var a = new Foo("zhang","jake");
new Foo{
var obj = {};
obj.__proto__ = Foo.prototype;
var result = Foo.call(obj,"zhang","jake");
return typeof result === 'obj'? result : obj;
}
var name = "Jake";jiuzhixiang
function testThis(){
this.name = 'jakezhang';
this.sayName = function () {
return this.name;
}
}
console.log(this.name ); // Jake
new testThis();
console.log(this.name ); // Jake
var result = new testThis();
console.log(result.name ); // jakezhang
console.log(result.sayName()); // jakezhang
testThis();
console.log(this.name ); // jakezhang
class中的this:
可以指向任何新创建的对象。
call、apply和bind中的this:
call、apply、bind 俗称为this 的强行绑定用来改变函数执行时的this指向
class Hero {
constructor(heroName) {
this.heroName = heroName;
}
dialogue() {
console.log(`I am ${this.heroName}`)
}
}
const batman = new Hero("Batman");
batman.dialogue();
const say = batman.dialogue;
say();
箭头函数的this:
使用 call 、 apply, bind给 this传值,箭头函数会忽略。箭头函数会引用创建时设置的this的值
this是javascript的一个关键字,随着函数使用场合不同,this的值会发生变化。但是总有一个原则,那就是this指的是调用函数的那个对象。
this一般指向的是当前被调用者,但也可以通过其它方式来改变它的指向,下面将介绍三种方式
let name = "zjk";
let o = {
name : "Jake",
sayName: function () {
console.log(this.name)
},
func: function () {
setTimeout( () => {
this.sayName()
},100);
}
};
o.func() // Jake
let obj = {
name: "Jake",
func: (a,b) => {
console.log(this.name,a,b);
}
};
func.call(obj,1,2);// 1 2
func.apply(obj,[1,2]);// 1 2
var number = 1;
var obj = {
number:2,
showNumber:function(){
this.number = 3;
(function(){
console.log(this.number);
})();
console.log(this.number);
}
};
obj.showNumber();
call、apply和bind的区别:
三者的共同点:
都是改变this指向的
不同点:call()/apply() ======>bind()
bing():
将this指向修改this指向,需要加 ( ) 才能执行
call()、apply()不同点:
在于第二个参数,call第二个参数是一个一个的数据,apply第二个参数是数组
共同点:
将this指向第一个参数
应用场景:
伪数组借用数组方法 NodeList/arguments
// function fn() {
// console.log(arguments);
// // 要往arguments集合中追加一个数100;
// // arguments.push(100);
// // Array.prototype.push.call(arguments, 100)
// // 往arguments集合中追加多个值,[100,200,300]
// // Array.prototype.pop.call(arguments)
// [].pop.bind(arguments)();
// console.log(arguments);
// }
// fn(3, 4, 5, 6);
var name = '王五'
var obj = {
name: '张三',
fn() {
console.log(this.name)
}
}
var pox = {
name: '李四'
}
obj.fn.bind(pox)();