Rumah  >  Artikel  >  Artikel untuk memahami panduan ini dan mengejar 70% orang hadapan

Artikel untuk memahami panduan ini dan mengejar 70% orang hadapan

青灯夜游
青灯夜游ke hadapan
2022-09-06 17:03:132893semak imbas

Seorang rakan sekerja terperangkap pada bug dan vue2的this指向问题 kerana masalah yang ditunjukkan oleh ini, dia menggunakan fungsi anak panah, mengakibatkan kegagalan untuk mendapatkan props yang sepadan. Dia tidak tahu apabila saya memperkenalkannya kepadanya, dan kemudian saya sengaja melihat kumpulan pertukaran bahagian hadapan Setakat ini, sekurang-kurangnya 70% pengaturcara bahagian hadapan masih tidak memahaminya anda penunjuk this Jika saya tidak belajar apa-apa, sila berikan saya mulut yang besar.

1. Lokasi panggilan

  • Skop berkaitan dengan tempat ia ditakrifkan, bukan di mana ia dilaksanakan
  • this menunjuk kepada Ia tiada kaitan dengan tempat ia ditakrifkan, ia bergantung pada cara memanggilnya dan dalam bentuk apa
  • this(ini) Bagaimana fungsi ini dipanggil (untuk memudahkan ingatan)
  • Untuk memudahkan pemahaman, secara lalai ia tidak Menghidupkan mod ketat

2. Peraturan mengikat

Kami memperkenalkan di atas bahawa penunjuk this terutamanya berkaitan dengan bentuk panggilan. Seterusnya, saya akan memperkenalkan peraturan panggilan kepada anda Tanpa peraturan, tidak ada yang lengkap.

  • Anda mesti mencari lokasi panggilan, dan kemudian tentukan yang mana antara empat peraturan mengikat berikut
  • Kedua, anda juga mesti mengetahui keutamaan empat peraturan mengikat ini >
  • Anda tahu kedua-dua perkara ini adalah mudah untuk anda mengetahui arah ini

2.1 Pengikatan lalai

Fungsi adalah yang paling biasa digunakan. kaedah panggilan, jenis fungsi panggilan: panggilan fungsi bebas

function bar() {
  console.log(this) // window
}
    bar ialah panggilan langsung tanpa sebarang pengubah suai, jadi pengikatan lalai ialah
  • window
  • dalam In strict mod,
  • di sini ialah thisundefined

2.2 Pengikatan tersirat

Dalam istilah yang paling popular, ia bermakna: objek mempunyai kaedah tertentu , akses kaedah melalui objek ini dan panggil terus (nota: fungsi anak panah adalah istimewa dan akan diterangkan di bawah)

const info = {
  fullName: 'ice',
  getName: function() {
    console.log(this.fullName)
  }
}

info.getName() // 'ice'
    Fungsi ini dipanggil oleh
  • dan terikat secara tersirat, jadi pada masa ini info ialah this, dan melalui info tiada keraguan bahawa nilai akses ialah this.fullNameice

Biasa

hilang secara tersirat. Dalam kes ini, kehilangan tersirat akan dilakukan Fungsi terikat secara tersirat akan kehilangan objek pengikat, yang bermaksud ia menjadi nilai pengikatan lalai > atau

Bergantung pada persekitaran anda sekarang, sama ada dalam mod ketat. thiswindowundefined   Dalam kes ini, kehilangan tersirat dilakukan dan objek terikat hilang Mengapa masalah sedemikian berlaku? Jika anda biasa dengan ingatan, ia akan mudah difahami.

const info = {
  fullName: 'ice',
  getName: function() {
    console.log(this.fullName)
  }
}

const fn = info.getName

fn() //undefined

tidak dipanggil terus di sini, tetapi alamat memori yang sepadan dengan

ditemui melalui
    , diberikan kepada pembolehubah
  • infogetName dan kemudian terus melalui fn Sebenarnya, intipati di sini adalah untuk memanggil fungsi bebas, iaitu
  • Ambil atribut
  • daripada fn dan ia mestilah
  • windowwindowfullNameTersirat. Loss Advancedundefined
  • Di sini anda mesti memahami apa itu fungsi panggil balik. Malah, ia boleh difahami dengan cara ini, iaitu, saya tidak memanggilnya sekarang, tetapi menyampaikannya ke tempat lain dalam bentuk parameter, dan memanggilnya di tempat lain.

Pertama sekali,
dalam

ialah fungsi panggil balik
//申明变量关键字必须为var
var fullName = 'panpan'

const info = {
  fullName: 'ice',
  getName: function() {
    console.log(this.fullName)
  }
}

function bar(fn) {
  //fn = info.getName
  fn() // panpan
}

bar(info.getName)
  • Hantaran parameter ialah sejenis tugasan tersirat, yang sebenarnya sama sebagai kehilangan tersirat di atas Ia bermaksud perkara yang sama, mereka semua menunjuk kepada bar rujukan, iaitu, alamat memori mereka fn
  • kerana
  • mereka hilang, iaitu, fungsi dipanggil secara bebas, peraturan mengikat lalai, fn = info.getName ialah global fn = info.getName objek
  • Nota: Mengapakah pengisytiharan mesti this? thiswindow Kerana hanya pembolehubah yang diisytiharkan oleh
  • akan ditambahkan pada objek
  • global var
      Jika
    • digunakan, perkara utama kedua-dua pembolehubah yang diisytiharkan ini akan diperkenalkan secara terperinci kemudian. varwindow
    • 2.3 Pengikatan Paparan letconst
      Tetapi dalam sesetengah senario, perubahan
  • adalah tidak dijangka, dan sebenarnya kami tidak mempunyai kawalan ke atas cara fungsi panggil balik pelaksanaan, jadi tidak ada cara untuk mengawal bahawa lokasi panggilan telah mendapat pengikatan yang dijangkakan iaitu ini menunjuk kepada.
  • Ikatan paparan seterusnya boleh digunakan untuk menyelesaikan masalah kehilangan tersirat ini.

2.3.1 call/apply/bind

Fungsi "Semua" dalam js mempunyai beberapa ciri berguna Ini berkaitan dengan rantaian prototaipnya memperkenalkan dalam prototaip kaedah melaksanakan pewarisan dalam bentuk terselindung dalam js melalui rantai prototaip Antaranya, this tiga kaedah ini ialah kaedah pada rantai prototaip fungsi, dan ia boleh dipanggil dalam fungsi.

2.3.2 call

  • call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
    • 第一个参数为固定绑定的this对象
    • 第二个参数以及二以后的参数,都是作为参数进行传递给所调用的函数
  • 备注
    • 该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组
var fullName = 'panpan'

const info = {
  fullName: 'ice',
  getName: function(age, height) {
    console.log(this.fullName, age, height)
  }
}

function bar(fn) {
  fn.call(info, 20, 1.88) //ice 20 1.88
}

bar(info.getName)

2.3.3 apply

  • call的方法类似,只是参数列表有所不同
    • 参数
      • call  参数为单个传递
      • apply 参数为数组传递
var fullName = 'panpan'

const info = {
  fullName: 'ice',
  getName: function(age, height) {
    console.log(this.fullName, age, height)
  }
}

function bar(fn) {
  fn.apply(info, [20, 1.88]) //ice 20 1.88
}

bar(info.getName)

2.3.4 bind

  • bindapply/call之间有所不同,bind传入this,则是返回一个this绑定后的函数,调用返回后的函数,就可以拿到期望的this。
  • 参数传递则是
    • 调用bind时,可以传入参数
    • 调用bind返回的参数也可以进行传参
var fullName = 'panpan'

const info = {
  fullName: 'ice',
  getName: function(age, height) {
    console.log(this.fullName, age, height) //ice 20 1.88
  }
}

function bar(fn) {
  let newFn = fn.bind(info, 20)
  newFn(1.88)
}

bar(info.getName)

2.4 new绑定

  谈到new关键字,就不得不谈构造函数,也就是JS中的 "类",后续原型篇章在跟大家继续探讨这个new关键字,首先要明白以下几点,new Fn()的时候发生了什么,有利于我们理解this的指向。

  • 创建了一个空对象

  • 将this指向所创建出来的对象

  • 把这个对象的[[prototype]] 指向了构造函数的prototype属性

  • 执行代码块代码

  • 如果没有明确返回一个非空对象,那么返回的对象就是这个创建出来的对象

function Person(name, age) {
  this.name = name
  this.age = age

}

const p1 = new Person('ice', 20)

console.log(p1) // {name:'ice', age:20}
  • 当我调用new Person()的时候,那个this所指向的其实就是p1对象

3. 绑定优先级

3.1 隐式绑定 > 默认绑定

function bar() {
  console.log(this) //info
}

const info = {
  bar: bar
}

info.bar()
  • 虽然这边比较有些勉强,有些开发者会认为这是默认绑定的规则不能直接的显示谁的优先级高
  • 但是从另外一个角度来看,隐式绑定,的this丢失以后this才会指向widonw或者undefined,变相的可以认为隐式绑定 > 默认绑定

3.2 显示绑定 > 隐式绑定

var fullName = 'global ice'
const info = {
  fullName: 'ice',
  getName: function() {
    console.log(this.fullName) 
  }
}

info.getName.call(this) //global ice
info.getName.apply(this) //global ice
info.getName.bind(this)() //global ice
  • 通过隐式绑定和显示绑定的一起使用很明显 显示绑定 > 隐式绑定

3.3 bind(硬绑定) >  apply/call

function bar() {
  console.log(this) //123
}

const newFn = bar.bind(123)
newFn.call(456)

3.4 new绑定 > bind绑定

首先我们来说一下,为什么是和bind比较,而不能对callapply比较,思考下面代码

const info = {
  height: 1.88
}

function Person(name, age) {
  this.name = name
  this.age = age
}

const p1 = new Person.call('ice', 20)

//报错: Uncaught TypeError: Person.call is not a constructor

new绑定和bind绑定比较

const info = {
  height: 1.88
}

function Person(name, age) {
  this.name = name
  this.age = age
}

const hasBindPerson = Person.bind(info)

const p1 = new hasBindPerson('ice', 20)

console.log(info) //{height: 1.88}
  • 我们通过bindPerson进行了一次劫持,硬绑定了this为info对象
  • new 返回的固定this的函数
  • 但是我们发现 并不能干预this的指向

3.5 总结

new关键字 > bind > apply/call > 隐式绑定 > 默认绑定

4. 箭头函数 (arrow function)

首先箭头函数是ES6新增的语法

const foo = () => {}

4.1 箭头函数this

var fullName = 'global ice'

const info = {
  fullName: 'ice',
  getName: () => {
    console.log(this.fullName)
  }
}

info.getName() //global ice
  • 你会神奇的发现? 为什么不是默认绑定,打印结果为ice
  • 其实这是ES6的新特性,箭头函数不绑定this,它的this是上一层作用域,上一层作用域为window
  • 所以打印的结果是 global ice

4.2 箭头函数的应用场景 进阶

  • 需求: 在getObjName通过this拿到info中的fullName (值为icefullName)
const info = {
  fullName: 'ice',
  getName: function() {
    let _this = this
    return {
      fullName: 'panpan',
      getObjName: function() {
        console.log(this) // obj
        console.log(_this.fullName)
      }
    }
  }
}

const obj = info.getName()
obj.getObjName()
  • 当我调用 info.getName() 返回了一个新对象

  • 当我调用返回对象的getObjName方法时,我想拿到最外层的fullName,我通过,getObjName的this访问,拿到的this却是obj,不是我想要的结果

  • 我需要在调用info.getName() 把this保存下来,info.getName() 是通过隐式调用,所以它内部的this就是info对象

  • getObjName是obj对象,因为也是隐式绑定,this必定是obj对象,绕了一大圈我只是想拿到上层作用域的this而已,恰好箭头函数解决了这一问题

const info = {
  fullName: 'ice',
  getName: function() {
    return {
      fullName: 'panpan',
      getObjName: () => {
        console.log(this.fullName)
      }
    }
  }
}

const obj = info.getName()
obj.getObjName()

5. 总结

5.1 this的四种绑定规则

  • 默认绑定

  • 隐式绑定

  • 显示绑定 apply/call/bind(也称硬绑定)

  • new绑定

5.2 this的优先级 从高到低

  • new绑定

  • bind

  • call/apply

  • 隐式绑定

  • 默认绑定

6. 结语

  当一切都看起来不起作用的时候,我就会像个石匠一样去敲打石头,可能敲100次,石头没有任何反应,但是101次,石头可能就会裂为两半 我知道并不是第101次起了作用,而是前面积累所致。

  大家有疑惑可以在评论区留言 第一时间为大家解答。

(学习视频分享:web前端开发

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam