this 是什么
this即不是指向自身函数 也是不是指向函数的词法作用域
this是函数被调用的发生的绑定,指向什么取决与函数在哪里调用
this 的四种绑定规则
默认绑定
在非严格的模式下,默认绑定的this指向全局对象,严格模式下this指向undefined
//默认绑定
//默认绑定的this指向全局对象
function foo() {
var a = 1;
console.log(this === window);
console.log(this.a);
}
var a = 2;
foo(); //true 2
// 严格模式this绑定到undefined
function foo2() {
"use strict";
console.log(this.a);
}
foo2();//Uncaught TypeError: Cannot read properties of undefined (reading 'a')
隐式绑定
函数在调用位置,是否有上下文对象,如果有则隐式绑定到这个对象上
//隐式绑定
//使用对象来调用其内部的方法,该方法的this是指向该对象本身
var myObj = {
a:"name",
showName:function(){
console.log(this.a)//name
console.log(this);//{a: 'name', showName: ƒ}
}
}
myObj.showName();
显式绑定
通过apply call bind 将函数的this绑定到指定的对象上
// 显式绑定
// 改变函数执行时的this指向为myObj1
var myObj1 = {
a:"3",
}
function foo1(){
console.log(this.a);
}
foo1() //2
foo1.call(myObj1)//3
apply,call,bind三者的区别
fun.call(thisArg, param1, param2,…)call方法的第一个参数是this的指向,后面传入的是一个参数列表
fun.apply(thisArg,[param1,param2,…])和call基本上一致,唯一区别在于传参方式
fun.bind(thisArg, param1,param2, …)语法和call一模一样,区别在于立即执行还是等待执行
- 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window。
- 三者都可以传参,但是apply是数组,而call是参数列表
- bind 是返回绑定this之后的函数,便于稍后调用;apply 、call则是立即执行
//call、apply和bind异同
var myObj2 = {
name:"name",
myage:"10",
myFun(x,y){
console.log(this.name,this.age,x,y);
}
}
myObj2.myFun() //name undefined
var myObj3 = {
name:"aaa",
age:"10"
}
//区别
myObj2.myFun.call(myObj3,33,44) //aaa 10 33 44
myObj2.myFun.apply(myObj3,[55,66]) //aaa 10 55 66
myObj2.myFun.bind(myObj3,77,88)() //aaa 10 77 88
应用
//1 call应用
function Father(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
function Son(name){
//借用父类的方法:修改它的this指向,赋值父类的构造函数里面方法、属性到子类上
Father.call(this,name)
}
var son = new Son("小明");
console.log(son.name);//小明
console.log(son.colors);//['red', 'blue', 'green']
//判断原生引用类型
console.log(Object.prototype.toString.call([1,2,3]));//[object Array]
console.log(Object.prototype.toString.call(123)); //[object Number]
//2 apply应用
var arr = [15, 6, 12, 13, 16];
console.log(Math.max(15, 6, 12, 13, 16)); //16
console.log(Math.max.apply(Math,arr)); //16
//3 bind应用
/* for(var i =0;i<=5;i++){
setTimeout(function(){
console.log(i); //6个6
},i*1000)
}*/
for(var i =0;i<=5;i++){
setTimeout(function(i){
console.log(i); //0 1 2 3 4 5
}.bind(this,i),i*1000)
}
new绑定
通过构造函数中设置,使用构造调用的时候,this会自动绑定在new 期间创建的对象上
// new绑定
function Foo(name) {
this.name = name;
}
var a = new Foo("aaa");
console.log(a.name);//"aaa"
//1 创建一个全新的对象
//2 给新对象的内部属性赋值,构造原型链
//3 这个新对象会绑定到函数调用的this
//4 如果函数没有返回其他对象,那么会自动返回这个新对象
箭头函数
箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this
//箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。
var c= "c"
let o = {
c : "ccc",
func: function () {
let showName = () => {
console.log(this) //{c: 'ccc', func: ƒ}
console.log(this.c) //ccc
};
showName();
}
};
o.func()
参考
1https://juejin.cn/post/6844903630592540686#heading-1
2 https://juejin.cn/post/6844904009308831751#heading-10
3 《你不知道的JavaScript》第二章