对this的二次认知(一)

93 阅读4分钟

对this的二次认知(一)

😸😸😸最近在深入学习js的时候,js的复杂性在不断地刷新本人的认知,幸运的是之前对js还是有一点基础的,所以学起来更多的是收获惊喜,每一个小小的代码语句背后,都有非常奇妙的引擎处理过程,这也成就的js的与众不同。

🐧🐧🐧之前已经写过一篇关于this的文章,那已经是半年前的暑假了,现在回顾起来,当时写this的时候还只是小白,写得并不是很全面,起码没我现在对this的理解更清晰,更深入,所以来更新一下本人对于this的理解。

1. 为什么会存在this呢?

🌸1. 语言角度:几乎常见的面向对象语言中都存在this这个关键字,比如JavaC++,但是this通常只会出现在类的方法中,这一点我相信接触过上述语言的都清楚,而js中的this更加灵活,不懂得this的指向,就其对于js重要性而言我觉得你有点遗憾了。

🌸2.灵活性:this的指向并不是固定的,在任何时候,当我们清楚了this的指向,我们书写代码的时候更加方便,灵活。

可能其中还有很多原因,但还得等本人功力加深再谈。

2. this指向什么呢?

前奏知识

❄️1.所有的函数在被调用时,都会创建一个函数执行上下文

❄️2.这个上下文中记录着函数的调用栈、VO对象、作用域链、执行代码等等

❄️3.this也是一条其中的记录

❄️4.this通常在函数中使用

❄️5.this指向并不固定(一般情况指向一个对象),跟函数定义的位置并无瓜葛

❄️6.任何情况下,this的值不可修改

❗️❗️❗️this的绑定与函数的调用方式以及调用位置有关系

主要有如下四种绑定规则:

3.规则一:默认绑定

🍁什么情况下使用默认绑定呢?

独立函数调用:可以理解成函数没有被绑定到某个对象上进行调用,默认指向windwo

🍁案例一:

function foo() {
    console.log(this); 
}
​
//独立函数调用
foo() //window

🍁案例二:

var obj = {
    name: "obj",
    foo: function () {
        console.log(this);
    }
}
​
//obj.foo是函数的地址
var fn = obj.foo//独立函数调用
fn()//window

🍁案例三:

//这里参数是函数
function fn(foo) {
    foo()
}
​
var obj = {
    name: "obj",
    foo: function () {
        console.log(this);
    }
}
​
//独立函数调用 obj.foo代表函数地址 但函数是自己执行
fn(obj.foo) //window

🍁案例四:

function test1() {
    console.log(this); //window
    test2()
}
​
function test2() {
    console.log(this); //window
    test3()
}
function test3() {
    console.log(this); //window
}
​
//独立函数调用
test1()

4.规则二:隐式绑定

🌿函数调用方式是通过某个对象调用的(函数作为对象的属性,俗称:对象的方法)

🌿案例一:

var obj = {
    name: "obj",
    foo: function () {
        console.log(this);
    }
}
​
obj.foo() //obj对象

🌿案例二:

function foo() {
    console.log(this);
}
​
var obj1 = {
    name: "obj1",
    foo: foo
}
​
var obj2 = {
    name: "obj2",
    obj1: obj1
}
​
//这里的调用对象不是obj2,obj2只是找到obj1的媒介,foo属性仍然挂在obj1对象上
obj2.obj1.foo() //obj1对象

🌿案例三:

var obj1 = {
    name: "obj1",
    foo: function () {
        console.log(this);
    }
}
​
var obj2 = {
    name: "obj2"
}
​
obj2.bar = obj1.foo//bar作为obj2的属性被调用
obj2.bar() //obj2对象

5.规则三:显示绑定

🌵通过js提过内置函数修改this指向

🌵callapplybind这里不谈这三种函数的使用方法和区别

🌵案例一:

function foo() {
    console.log(this);
}
​
foo.call(window) //window
foo.call("sss") //String {'sss'}
foo.call(156) //Number {156}

🌵案例二:固定函数的this绑定

function foo() {
    console.log(this);
}

var bar = foo.bind("me")
bar() //bar永远指向 String {'me'}

6.规则四:new绑定

🌏js中的函数可以当作一个类的构造器来使用,调用时使用new关键字

🌏使用new关键字来调用函数,会执行如下的操作:

  1. 创建一个全新的空的对象
  2. 这个新对象会和prototype连接
  3. 空的对象被分配给this(this指向这个对象)
  4. 函数体执行,通常会通过this为这个对象添加新的属性
  5. 函数默认返回this,也就是这个对象

🌏案例一:

function Person(name) {
    this.name = name
    console.log(this); //Person {name:'jack'}
    //默认返回this
}

var p = new Person('jack') 
console.log(p);//Person {name:'jack'}

7.总结

💖1.我觉得上述四个绑定规则如果能够掌握,起码this在你平常写代码的时候能够拿捏自如,相比我的上一篇关于this指向来说,这次写得就很系统化,基本涵盖了this的所有使用情况,理解才是王道

💖2.我万万没有想到我写到这里的时候已经花了两个小时了,但关于this的认知并没有写完,下一篇博客将完结我对this的理解

💖3.虽然花费了两个小时,但是很有价值,我觉得我真正在这个过程中掌握这些知识的,前几天看了一篇优秀学习方法:费曼学习法的博客,学习过程中,我们更需要主动学习,而不是被动学习,博客地址我分享在这里:

优秀的学习方法 - 费曼学习法 - 掘金 (juejin.cn)

借用一句电影台词作为结束语吧:

成年人的生活里,没有容易二字。

——《天气预报员》

哈哈,我还不想把自己当作成年人看待,但悄然发现自己的思想已不再稚嫩。