Các phương thức trong các đối tượng ES6: sử dụng các hàm mũi tên


96

Trong ES6, cả hai điều này đều hợp pháp:

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

và, viết tắt:

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

Có thể sử dụng các chức năng mũi tên mới không? Đang thử một cái gì đó như

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

hoặc là

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

Tôi nhận được thông báo lỗi cho thấy rằng phương pháp không có quyền truy cập this. Đây chỉ là vấn đề về cú pháp hay bạn không thể sử dụng các phương thức fat-pipe bên trong các đối tượng ES6?


11
Một trong những điểm lớn nhất của cú pháp hàm mới là nó xử lý thiskhác nhau. Nó được xác định bởi môi trường từ vựng nơi hàm được tạo, có nghĩa là thisgiá trị mà bạn tạo chopperbiến sẽ là thisgiá trị của hàm. Nói cách khác, nó sẽ không tham chiếu đến chopperđối tượng.

1
Trong khi sử dụng cú pháp mũi tên béo? Chỉ khi bạn thay đổi thisgiá trị bằng cách tạo chopperđối tượng trước, sau đó thực hiện phép gán trong một hàm đã thistrỏ đến đối tượng đó. Điều này có thể được thực hiện khá rõ ràng với một hàm khởi tạo.

1
Bản trình diễn này sẽ chạy trên Firefox. Chrome chưa có nó. jsfiddle.net/bfyarxfe

2
@fox, bạn phải sử dụng 'sử dụng nghiêm ngặt' trên jsfiddle đó.
Walter Chapilliquen - wZVanG

1
@fox: Nó hoạt động tốt trong môi trường được hỗ trợ. Firefox chưa có hỗ trợ đầy đủ. Hãy thử nó trong Continuumconsole.log()kết quả của cuộc gọi phương thức. Nó hoạt động.

Câu trả lời:


154

Các hàm mũi tên không được thiết kế để sử dụng trong mọi tình huống chỉ đơn thuần là một phiên bản ngắn hơn của các hàm kiểu cũ. Chúng không nhằm thay thế cú pháp hàm bằng functiontừ khóa. Trường hợp sử dụng phổ biến nhất cho các hàm mũi tên là "lambdas" ngắn không xác định lại this, thường được sử dụng khi chuyển một hàm dưới dạng gọi lại cho một số hàm.

Không thể sử dụng các hàm mũi tên để viết các phương thức đối tượng bởi vì, như bạn đã tìm thấy, vì các hàm mũi tên đóng trên thisngữ cảnh bao quanh từ vựng, thisbên trong mũi tên là hàm hiện tại mà bạn đã xác định đối tượng. Đó là để nói:

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

Trong trường hợp của bạn, muốn viết một phương thức trên một đối tượng, bạn chỉ nên sử dụng functioncú pháp truyền thống hoặc cú pháp phương thức được giới thiệu trong ES6:

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

// or

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

(Có những khác biệt nhỏ giữa chúng, nhưng chúng chỉ quan trọng nếu bạn sử dụng supertrong getOwnerđó, bạn không sử dụng hoặc nếu bạn sao chép getOwnersang một đối tượng khác.)

Đã có một số cuộc tranh luận trên danh sách gửi thư es6 về một sự thay đổi trong các hàm mũi tên có cú pháp tương tự nhưng với cú pháp riêng của chúng this. Tuy nhiên, đề xuất này không được đón nhận nhiều vì đó chỉ là cú pháp cú pháp, cho phép mọi người tiết kiệm việc nhập một vài ký tự và không cung cấp chức năng mới so với cú pháp hàm hiện có. Xem các chức năng mũi tên không liên kết chủ đề .


Nếu tôi đang đọc điều này một cách chính xác, có vẻ như cho thấy rằng danh sách gửi thư làm mất đi đường cú pháp, ngay cả khi nó sẽ dẫn đến tính đồng nhất / dễ đọc hơn của mã. Như hiện tại, việc sử dụng các hàm mũi tên béo trong ngữ cảnh OOP dưới ES6 sẽ khó hơn nhiều so với trong coffeescript.
fox

Theo tôi hiểu, đường cú pháp được coi là lý do hợp lệ để xem xét mở rộng ngôn ngữ, nhưng như bạn nói với mức độ ưu tiên thấp hơn - nói cách khác, thanh cao hơn cho các đề xuất như vậy.

12

Trong dòng này getOwner: => (this.owner)phải là:

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

Bạn sẽ phải khai báo thisthành một hàm:

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

Hoặc là:

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
Tôi gặp lỗi ở đây:"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner
fox

Tôi hiểu, đó là cách sử dụng chính xác, tuy nhiên phương thức esta luôn trả về đối tượng cửa sổ. Bạn sẽ phải khai báo thistrong một hàm.
Walter Chapilliquen - wZVanG

2
thiskhông nhất thiết phải đề cập đến window. Nó đề cập đến bất kỳ giá trị hiện tại nào thistrong môi trường bao quanh, có thể có hoặc không window. Có lẽ đó là những gì bạn muốn nói. Chỉ muốn đảm bảo rằng anh ấy hiểu nó không phải là một số giá trị mặc định.

@torazaburo Đó là tốt cho tôi, tôi đã thử nó, thishiện nay đề cập đến lớp
Walter Chapilliquen - wZVanG

2
Những gì bạn đã viết tương đương với, nhưng dài dòng hơn là viết đơn giản var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }.

1

Một mẹo nhanh mà tôi làm theo để sử dụng các chức năng mũi tên.

  • Sử dụng các hàm không phải mũi tên cho các phương thức sẽ sử dụng object.method()cú pháp. (Đó là những chức năng sẽ nhận được ý nghĩathis giá trị từ người gọi của chúng.)
  • Sử dụng chức năng mũi tên cho hầu hết mọi thứ khác.


0

Nếu bạn phải sử dụng chức năng mũi tên, bạn có thể thay đổi thisthành chopper,

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

Mặc dù đây không phải là phương pháp hay nhất, nhưng khi bạn thay đổi tên đối tượng, bạn phải thay đổi chức năng mũi tên này.


0

Một mẹo khác, ở chế độ nghiêm ngặt, thisvẫn đề cập đến Window thay vì không xác định.

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

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.