Rumah  >  Artikel  >  hujung hadapan web  >  Adakah gula sintaksis kelas es6?

Adakah gula sintaksis kelas es6?

青灯夜游
青灯夜游asal
2022-10-17 18:03:101865semak imbas

kelas ialah gula sintaksis. Sebab: kelas adalah berdasarkan pelaksanaan pewarisan prototaip, yang tidak memberi kesan kepada fungsi bahasa Ia hanya memudahkan penulisan dan pembacaan tatabahasa; lebih seperti tatabahasa pengaturcaraan berorientasikan objek.

Adakah gula sintaksis kelas es6?

Persekitaran pengendalian tutorial ini: sistem Windows 7, ECMAScript versi 6, komputer Dell G3.

Kelas kelas ES6 - gula sintaksis

kelas (kelas) diperkenalkan sebagai templat untuk objek, dan kelas boleh ditakrifkan melalui kelas kata kunci. Intipatinya ialah fungsi, yang boleh dianggap sebagai gula sintaksis, menjadikan kaedah penulisan prototaip objek lebih jelas dan lebih seperti sintaks pengaturcaraan berorientasikan objek.

Kelasnya berbeza daripada bahasa lain Ia masih berdasarkan warisan prototaip, yang tidak memberi kesan kepada fungsi bahasa Ia hanya memudahkan penulisan dan pembacaan anda

Mengapa dikatakan kelas ES6 adalah gula sintaksis

Mari baca yang berikut dengan soalan:

  • Mengapa dikatakan kelas ES6 adalah sintaksis gula?
  • Adakah kelas gula sintaksis prototaip?
  • Kemudian bagaimana anda menggunakan prototaip untuk melaksanakan gula sintaksis kelas?

1 OOP berasaskan prototaip

Mari kita lihat contoh prototaip dahulu:

function Person (name, sex) {
	this.name = name
	this.sex = sex
}
 
function Man (name) {
	this.name = name
}
 
Man.prototype = new Person('', 'male')
 
let Jy = new Man('Jy')
 
console.log(Jy.name, Jy.sex) // Jy, male

Ini adalah contoh yang sangat mudah tentang cara kami menggunakan prototaip Orang mempunyai nama dan jantina, Lelaki ialah Orang dengan jantina lelaki, dan Jy ialah Lelaki. Mari kita ingat contoh ini dahulu, dan kita akan menulis semula contoh ini menggunakan kelas di bawah.

Petua: baharu, ini, dsb. telah ditambahkan oleh Brendan Eich untuk menjadikannya lebih seperti OOP Java. Pembaca yang berminat boleh menyemak sendiri maklumat yang berkaitan.

2 OOP Kelas ES6

class Person {
	constructor (name, sex) {
		this.name = name
		this.sex = sex
	}
}
 
class Man extends Person {
	constructor (name) {
		super('', 'male')
		this.name = name
	}
}
 
let Jy = new Man('Jy')
 
console.log(Jy.name, Jy.sex) // Jy, 'male'

Kami menulis semula contoh ini dan menggunakan kelas, pembina, extends , perkataan super. , mari kita bercakap secara khusus tentang perkara yang dilakukan kepada mereka dalam spesifikasi ES6.

3. Kelas OOP dilaksanakan menggunakan Prototaip (spesifikasi ES6)

Sebelum ES6, objek JS sebenarnya adalah koleksi atribut dan atribut Ia adalah satu set pasangan nilai kunci (kunci, nilai).

Anda mengatakan bahawa atribut biasa adalah baik, tetapi tidakkah terdapat kaedah di bawah objek? Bagaimanakah ia menjadi koleksi atribut?

Malah, takrif kaedah yang muncul dalam spesifikasi ES5 ialah "fungsi yang merupakan nilai harta", yang hanya atribut fungsi objek dan tidak boleh dipanggil kaedah sehingga ES6 muncul bahawa Kaedah disertakan dalam spesifikasi.

Kita boleh memikirkan perkara yang berkaitan dengan OOP dalam ES3: prototaip, baru, ini, pembina, instanceof, malah bukan atribut __proto__ standard.

Nasib baik, dalam ES5 kami telah menambah banyak kaedah untuk melengkapkannya dan menjadikannya lengkap:

  • Object.defineProperty
  • Object.freeze
  • Object.create
  • Object.getPrototypeOf
  • Object.setPrototypeOf
  • isPrototypeOf
  • ......

Jom lihat sekeping kod sekali lagi:

let obj = {
	name: 'Jy',
	speak () { // Note: it's not speak: function () {}
		console.log(this.name, super.name)
	}
}
 
obj.speak() // Jy, undefined
 
Object.setPrototypeOf(obj,  { name: 'super' })
 
obj.speak() // Jy, super
 
let speak = obj.speak
speak() // undefined, super

obj.speak ditakrifkan sebagai Kaedah dalam ES6 Ia mempunyai atribut [[homeObject]] dan homeObject menunjuk ke objek yang kaedah dipanggil (. kod itu merujuk kepada obj ), ia ialah Slot Dalaman yang terikat pada objek, iaitu, anda tidak boleh mengubah suainya, yang bersamaan dengan dikod keras.

Jadi apakah kegunaan homeObject? Ia berkait rapat dengan super Apabila kata kunci super dihuraikan, prototaip homeObject akan ditemui.

Ringkasnya, ia boleh diringkaskan sebagai dua formula berikut:

  • let homeObj = Method[[HomeObject]] = obj
  • super = Object .getPrototypeOf(homeObj )

Nota: homeObject terikat secara statik dalam slot dalaman, manakala super dicari secara dinamik.

Selepas bercakap tentang super, mari bercakap tentang extends dan constructor

class A extends B { }
 
class A extends B {
	constructor (...args) {
		super(args)
	}
}
 
class C extends null { }

extends terutamanya melakukan dua perkara berikut:

  • Object.setPrototypeOf ( A, B)
  • Object.setPrototypeOf(A.prototype, B.prototype)

Jika kelas induk adalah null, laksanakan Object.setPrototypeOf(C.prototype, null)

Perbezaan antara bahagian pertama dan kedua kod di atas ialah sama ada pembina diisytiharkan secara eksplisit Jadi adakah kedua-dua keping kod ini bersamaan? Jawapannya setara.

Ini adalah cara ia ditakrifkan dalam spesifikasi:

Bahagian ketiga kod mewarisi null Ia tidak akan melaporkan ralat sintaks, tetapi kami tidak boleh mencipta C baharu kerana ia akan Memanggil pembina null, tetapi null tidak mempunyai pembina.

Melihat di sini, pengisytiharan oop kelas dan spesifikasi ES6 semuanya menggunakan prototaip untuk beroperasi, jadi bolehkah kita katakan bahawa kelas ialah gula sintaks prototaip?

4. Babel compiled class

Dalam projek sebenar kami, kami sering menggunakan babel untuk menyusun kod ES6 dan 7, jadi dalam bahagian ini kami Mari kita analisis kod yang disusun Babel berikut, yang akan mengetepikan beberapa pelaporan ralat dan kod berkaitan pengesanan untuk mempersembahkan tema penggunaan prototaip untuk melaksanakan OOP dengan lebih baik.

Sebelum kompilasi:

class A extends B {}
 
console.log(new A)

Selepas penyusunan:

"use strict";
 
function _getPrototypeOf(o) {
  _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
    return o.__proto__ || Object.getPrototypeOf(o);
  };
  return _getPrototypeOf(o);
}
 
function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  });
  if (superClass) _setPrototypeOf(subClass, superClass);
}
 
function _setPrototypeOf(o, p) {
  _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
    o.__proto__ = p;
    return o;
  };
  return _setPrototypeOf(o, p);
}
 
var A =
  /*#__PURE__*/
  function (_B) {
    _inherits(A, _B);
 
    function A() {
 
      return _getPrototypeOf(A).apply(this, arguments);
    }
 
    return A;
  }(B);
 
console.log(new A());

我们重点看_inherits 方法,跟我们上述说的extends做的两件事是一样的:

  • Object.setPrototypeOf(subClass, superClass)
  • Object.setPrototypeOf(subClass.prototype, superClass.prototype)

只不过它采用的是Object.create方法,这两个方法的区别可以去MDN上查看。

再看function A内部,其实就是执行了B的构造器函数来达到super(arguments)的效果, 这个与规范:如果没有显示声明constructor会自动加上constructor是一致的。

5. 总结

至此,我们终于理解了为什么class是原型的语法糖以及如何使用原型来实现class这一语法糖。

但切记我们使用原型的目的并不是来模拟class oop的,prototype based的oop应该用prototype去理解而不是class。

ES6的class oop 是不完备的 ,例如abstract class 、interface、private等都还没有,不过有些功能已经在提案中了,大家可以拥抱它,或者TypeScript是个不错的选择,如果你的项目中使用到了TS, 欢迎你到评论区分享你的感受。

【相关推荐:javascript视频教程编程视频

Atas ialah kandungan terperinci Adakah gula sintaksis kelas es6?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn