Metode dalam objek ES6: menggunakan fungsi panah


96

Di ES6, keduanya legal:

var chopper = {
    owner: 'Zed',
    getOwner: function() { return this.owner; }
};

dan, sebagai singkatan:

var chopper = {
    owner: 'Zed',
    getOwner() { return this.owner; }
}

Apakah mungkin untuk menggunakan fungsi panah baru juga? Dalam mencoba sesuatu seperti

var chopper = {
    owner: 'John',
    getOwner: () => { return this.owner; }
};

atau

var chopper = {
    owner: 'John',
    getOwner: () => (this.owner)
};

Saya mendapatkan pesan kesalahan yang menunjukkan bahwa metode tersebut tidak memiliki akses ke this. Apakah ini hanya masalah sintaks, atau Anda tidak dapat menggunakan metode pipa lemak di dalam objek ES6?


11
Salah satu poin terbesar dari sintaks fungsi baru adalah bahwa ia memperlakukannya secara thisberbeda. Ini ditentukan oleh lingkungan leksikal tempat fungsi itu dibuat, yang berarti thisnilai tempat Anda membuat choppervariabel akan menjadi thisnilai fungsi. Dengan kata lain, itu tidak akan mereferensikan chopperobjek.

1
Saat menggunakan sintaks panah lemak? Hanya jika Anda mengubah thisnilainya dengan membuat chopperobjek terlebih dahulu , kemudian melakukan tugas dalam fungsi yang thismengarah ke objek tersebut. Ini dapat diselesaikan dengan cukup rapi dengan fungsi konstruktor.

1
Demo ini akan berjalan di Firefox. Chrome belum memilikinya. jsfiddle.net/bfyarxfe

2
@fox, Anda harus menggunakan 'gunakan ketat' di jsfiddle itu.
Walter Chapilliquen - wZVanG

1
@fox: Ini berfungsi dengan baik dalam lingkungan yang didukung. Firefox belum memiliki dukungan lengkap. Cobalah di Continuum dan console.log()hasil dari pemanggilan metode. Berhasil.

Jawaban:


155

Fungsi panah tidak dirancang untuk digunakan dalam setiap situasi hanya sebagai versi pendek dari fungsi kuno. Mereka tidak dimaksudkan untuk menggantikan sintaks fungsi menggunakan functionkata kunci. Kasus penggunaan paling umum untuk fungsi panah adalah "lambda" singkat yang tidak didefinisikan ulang this, sering digunakan saat meneruskan fungsi sebagai callback ke beberapa fungsi.

Fungsi panah tidak dapat digunakan untuk menulis metode objek karena, seperti yang Anda temukan, karena fungsi panah dekat dengan thiskonteks yang melingkupi secara leksikal, thispanah di dalam adalah yang ada saat ini di mana Anda mendefinisikan objek. Artinya:

// Whatever `this` is here...
var chopper = {
    owner: 'Zed',
    getOwner: () => {
        return this.owner;    // ...is what `this` is here.
    }
};

Dalam kasus Anda, ingin menulis metode pada objek, Anda cukup menggunakan functionsintaks tradisional , atau sintaks metode yang diperkenalkan di ES6:

var chopper = {
    owner: 'Zed',
    getOwner: function() {
        return this.owner;
    }
};

// or

var chopper = {
    owner: 'Zed',
    getOwner() {
        return this.owner;
    }
};

(Ada perbedaan kecil antara mereka, tapi mereka hanya penting jika Anda menggunakan superdalam getOwner, yang Anda tidak, atau jika Anda menyalin getOwnerke obyek lain.)

Ada beberapa perdebatan di milis es6 tentang twist pada fungsi panah yang memiliki sintaks yang mirip tetapi dengan fungsinya sendiri this. Namun, proposal ini diterima dengan buruk karena itu hanyalah gula sintaks, memungkinkan orang untuk menyimpan pengetikan beberapa karakter, dan tidak menyediakan fungsionalitas baru atas sintaks fungsi yang ada. Lihat topik fungsi panah tak terikat .


Jika saya membacanya dengan benar, tampaknya hal ini menunjukkan bahwa milis menurunkan prioritas gula sintaksis, bahkan jika itu akan menyebabkan keseragaman / keterbacaan kode yang lebih besar. Seperti berdiri, jauh lebih menantang untuk menggunakan fungsi panah lemak dalam konteks OOP di bawah ES6 daripada, katakanlah, di bawah coffeescript.
rubah

Seperti yang saya mengerti, gula sintaksis adalah dianggap alasan yang sah untuk mempertimbangkan ekstensi bahasa, tapi seperti yang Anda katakan dengan prioritas yang lebih rendah - dengan kata lain, bar lebih tinggi untuk proposal tersebut.

12

Di baris ini getOwner: => (this.owner)seharusnya:

var chopper = {
    owner: 'John',
    getOwner: () => this.owner
}; //here `this` refers to `window` object.

Anda harus mendeklarasikan thismenjadi sebuah fungsi:

var chopper = {
    owner: 'John',
    getOwner() { return this.owner }
};

Atau:

var chopperFn = function(){

    this.setOwner = (name) => this.owner = name;
    Object.assign(this,{
        owner: 'Jhon',
        getOwner: () => this.owner,
    })

}

var chopper = new chopperFn();
console.log(chopper.getOwner());
chopper.setOwner('Spiderman');
console.log(chopper.getOwner());


1
Saya mendapatkan kesalahan di sini:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
rubah

Begitu, ini adalah penggunaan yang benar, namun metode esta selalu mengembalikan objek jendela. Anda harus mendeklarasikan di thisdalam suatu fungsi.
Walter Chapilliquen - wZVanG

2
thistidak selalu mengacu pada window. Ini mengacu pada apa pun nilai saat thisini di lingkungan penutup, yang mungkin atau mungkin tidak window. Mungkin itu yang kamu maksud. Hanya ingin memastikan dia mengerti itu bukan nilai default.

@torazaburo Tidak apa-apa bagi saya, saya mencobanya, thissekarang mengacu pada kelas
Walter Chapilliquen - wZVanG

2
Apa yang Anda tulis setara dengan, tetapi lebih bertele-tele daripada, sekadar menulis var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }.

1

Tip cepat yang saya ikuti untuk menggunakan fungsi panah.

  • Gunakan fungsi non-panah untuk metode yang akan menggunakan object.method()sintaks. (Itu adalah fungsi yang akan menerima thisnilai yang berarti dari pemanggilnya.)
  • Gunakan fungsi panah untuk hampir semua hal lainnya.


0

Jika Anda harus menggunakan fungsi panah, Anda dapat mengubah thiske chopper,

var chopper = {
  owner: "John",
  getOwner: () => chopper.owner
};

Meskipun ini bukan praktik terbaik, saat Anda mengubah nama objek, Anda harus mengubah fungsi panah ini.


0

Tip lain, dalam mode ketat, thismasih mengacu pada Window daripada undefined.

  (() => {
    "use strict";
    console.log(this); // window
  })();

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.