Giới thiệu ngắn gọn về phạm vi từ vựng là gì?
Giới thiệu ngắn gọn về phạm vi từ vựng là gì?
Câu trả lời:
Tôi hiểu họ thông qua các ví dụ. :)
Đầu tiên, phạm vi từ vựng (còn được gọi là phạm vi tĩnh ), theo cú pháp giống như C:
void fun()
{
int x = 5;
void fun2()
{
printf("%d", x);
}
}
Mỗi cấp độ bên trong có thể truy cập các cấp độ bên ngoài của nó.
Có một cách khác, được gọi là phạm vi động được sử dụng bởi lần triển khai đầu tiên của Lisp , một lần nữa theo cú pháp giống như C:
void fun()
{
printf("%d", x);
}
void dummy1()
{
int x = 5;
fun();
}
void dummy2()
{
int x = 10;
fun();
}
Ở đây fun
có thể truy cập x
vào dummy1
hoặc dummy2
, hoặc bất x
kỳ chức năng nào được gọi fun
với x
khai báo trong đó.
dummy1();
sẽ in 5,
dummy2();
sẽ in 10.
Cái đầu tiên được gọi là tĩnh bởi vì nó có thể được suy ra tại thời gian biên dịch và cái thứ hai được gọi là động vì phạm vi bên ngoài là động và phụ thuộc vào lệnh gọi chuỗi của các hàm.
Tôi tìm thấy phạm vi tĩnh dễ dàng hơn cho mắt. Hầu hết các ngôn ngữ đã đi theo cách này cuối cùng, ngay cả Lisp (có thể làm cả hai, phải không?). Phạm vi động giống như chuyển các tham chiếu của tất cả các biến sang hàm được gọi.
Như một ví dụ về lý do tại sao trình biên dịch không thể suy ra phạm vi động bên ngoài của hàm, hãy xem xét ví dụ cuối cùng của chúng tôi. Nếu chúng ta viết một cái gì đó như thế này:
if(/* some condition */)
dummy1();
else
dummy2();
Chuỗi cuộc gọi phụ thuộc vào một điều kiện thời gian chạy. Nếu đó là sự thật, thì chuỗi cuộc gọi trông như sau:
dummy1 --> fun()
Nếu điều kiện sai:
dummy2 --> fun()
Phạm vi bên ngoài của fun
trong cả hai trường hợp là người gọi cộng người gọi của người gọi và vân vân .
Chỉ cần đề cập rằng ngôn ngữ C không cho phép các hàm lồng nhau cũng như phạm vi động.
JavaScript
. Vì vậy, tôi nghĩ rằng điều này không nên được đánh dấu là câu trả lời được chấp nhận. Phạm vi từ vựng cụ thể trong JS là khác nhau
for
vòng lặp là vấn đề điển hình. Phạm vi từ điển cho JavaScript chỉ ở cấp độ chức năng trừ khi ES6 let
hoặc const
được sử dụng.
Hãy thử định nghĩa ngắn nhất có thể:
Lexical Scoping định nghĩa cách các tên biến được giải quyết trong các hàm lồng nhau: các hàm bên trong chứa phạm vi của các hàm cha ngay cả khi hàm cha đã trả về .
Đó là tất cả để có nó!
var scope = "I am global";
function whatismyscope(){
var scope = "I am just a local";
function func() {return scope;}
return func;
}
whatismyscope()()
Đoạn mã trên sẽ trả về "Tôi chỉ là người địa phương". Nó sẽ không trả lại "Tôi là một người toàn cầu". Bởi vì hàm func () tính nơi được xác định ban đầu nằm trong phạm vi của chức năng phân tích hàm.
Nó sẽ không bận tâm từ bất cứ thứ gì nó được gọi (phạm vi toàn cầu / từ bên trong một chức năng khác), đó là lý do tại sao giá trị phạm vi toàn cầu tôi là toàn cầu sẽ không được in.
Điều này được gọi là phạm vi từ vựng trong đó "các hàm được thực thi bằng chuỗi phạm vi có hiệu lực khi chúng được xác định " - theo Hướng dẫn định nghĩa JavaScript.
Phạm vi từ điển là một khái niệm rất rất mạnh mẽ.
Hi vọng điêu nay co ich..:)
Phạm vi từ vựng (tĩnh AKA) đề cập đến việc xác định phạm vi của một biến chỉ dựa trên vị trí của nó trong kho văn bản của mã. Một biến luôn đề cập đến môi trường cấp cao nhất của nó. Thật tốt khi hiểu nó liên quan đến phạm vi động.
Phạm vi xác định khu vực, nơi các chức năng, biến và như vậy có sẵn. Ví dụ, tính khả dụng của một biến được xác định trong ngữ cảnh của nó, giả sử hàm, tệp hoặc đối tượng, chúng được định nghĩa. Chúng ta thường gọi các biến cục bộ này.
Phần từ vựng có nghĩa là bạn có thể rút ra phạm vi từ việc đọc mã nguồn.
Phạm vi từ điển còn được gọi là phạm vi tĩnh.
Phạm vi động xác định các biến toàn cục có thể được gọi hoặc được tham chiếu từ bất kỳ đâu sau khi được xác định. Đôi khi chúng được gọi là biến toàn cục, mặc dù các biến toàn cục trong hầu hết các ngôn ngữ chương trình có phạm vi từ vựng. Điều này có nghĩa, nó có thể được bắt nguồn từ việc đọc mã mà biến có sẵn trong ngữ cảnh này. Có thể người ta phải tuân theo một mệnh đề sử dụng hoặc bao gồm mệnh đề hoặc định nghĩa, nhưng mã / trình biên dịch biết về biến ở nơi này.
Ngược lại, trong phạm vi động, bạn tìm kiếm trong hàm cục bộ, sau đó bạn tìm kiếm trong hàm gọi là hàm cục bộ, sau đó bạn tìm kiếm trong hàm gọi hàm đó, v.v., lên ngăn xếp cuộc gọi. "Động" đề cập đến sự thay đổi, trong đó ngăn xếp cuộc gọi có thể khác nhau mỗi khi một chức năng nhất định được gọi và do đó, chức năng có thể đạt các biến khác nhau tùy thuộc vào nơi nó được gọi. (xem tại đây )
Để xem một ví dụ thú vị cho phạm vi động xem tại đây .
Để biết thêm chi tiết xem tại đây và ở đây .
Một số ví dụ trong Delphi / Object Pascal
Delphi có phạm vi từ vựng.
unit Main;
uses aUnit; // makes available all variables in interface section of aUnit
interface
var aGlobal: string; // global in the scope of all units that use Main;
type
TmyClass = class
strict private aPrivateVar: Integer; // only known by objects of this class type
// lexical: within class definition,
// reserved word private
public aPublicVar: double; // known to everyboday that has access to a
// object of this class type
end;
implementation
var aLocalGlobal: string; // known to all functions following
// the definition in this unit
end.
Delphi gần nhất có phạm vi động là cặp hàm RegisterClass () / GetClass (). Đối với việc sử dụng của nó xem ở đây .
Giả sử thời gian mà RegisterClass ([TmyClass]) được gọi để đăng ký một lớp nhất định không thể dự đoán được bằng cách đọc mã (nó được gọi trong phương thức nhấp vào nút được gọi bởi người dùng), mã gọi GetClass ('TmyClass') sẽ nhận được một kết quả hay không Cuộc gọi đến RegisterClass () không phải nằm trong phạm vi từ vựng của đơn vị sử dụng GetClass ();
Một khả năng khác cho phạm vi động là các phương thức ẩn danh (bao đóng) trong Delphi 2009, vì chúng biết các biến của hàm gọi của chúng. Nó không đi theo con đường gọi từ đó một cách đệ quy và do đó không hoàn toàn năng động.
Tôi yêu các câu trả lời đầy đủ, không liên quan đến ngôn ngữ từ những người như @Arak. Vì câu hỏi này được gắn thẻ JavaScript , nên tôi muốn ghi chú trong một số ghi chú rất cụ thể cho ngôn ngữ này.
Trong JavaScript, các lựa chọn của chúng tôi cho phạm vi là:
var _this = this; function callback(){ console.log(_this); }
callback.bind(this)
Điều đáng chú ý, tôi nghĩ rằng JavaScript không thực sự có phạm vi động . .bind
điều chỉnh this
từ khóa, và đó là gần, nhưng về mặt kỹ thuật không giống nhau.
Dưới đây là một ví dụ minh họa cả hai cách tiếp cận. Bạn làm điều này mỗi khi bạn đưa ra quyết định về cách phạm vi các cuộc gọi lại để điều này áp dụng cho các lời hứa, xử lý sự kiện và hơn thế nữa.
Đây là những gì bạn có thể hạn Lexical Scoping
của cuộc gọi lại trong JavaScript:
var downloadManager = {
initialize: function() {
var _this = this; // Set up `_this` for lexical access
$('.downloadLink').on('click', function () {
_this.startDownload();
});
},
startDownload: function(){
this.thinking = true;
// Request the file from the server and bind more callbacks for when it returns success or failure
}
//...
};
Một cách khác để phạm vi là sử dụng Function.prototype.bind
:
var downloadManager = {
initialize: function() {
$('.downloadLink').on('click', function () {
this.startDownload();
}.bind(this)); // Create a function object bound to `this`
}
//...
Những phương pháp này, theo như tôi biết, tương đương với hành vi.
bind
không ảnh hưởng đến phạm vi.
IBM định nghĩa nó là:
Phần của một chương trình hoặc phân đoạn đơn vị áp dụng khai báo. Một định danh được khai báo trong một thường trình được biết đến trong thói quen đó và trong tất cả các thói quen lồng nhau. Nếu một thói quen lồng nhau khai báo một mục có cùng tên, thì mục bên ngoài không có sẵn trong thói quen lồng nhau.
Ví dụ 1:
function x() {
/*
Variable 'a' is only available to function 'x' and function 'y'.
In other words the area defined by 'x' is the lexical scope of
variable 'a'
*/
var a = "I am a";
function y() {
console.log( a )
}
y();
}
// outputs 'I am a'
x();
Ví dụ 2:
function x() {
var a = "I am a";
function y() {
/*
If a nested routine declares an item with the same name,
the outer item is not available in the nested routine.
*/
var a = 'I am inner a';
console.log( a )
}
y();
}
// outputs 'I am inner a'
x();
Phạm vi từ vựng có nghĩa là trong một nhóm các hàm lồng nhau, các hàm bên trong có quyền truy cập vào các biến và các tài nguyên khác trong phạm vi cha của chúng . Điều này có nghĩa là các hàm con bị ràng buộc về mặt từ vựng với bối cảnh thực thi của cha mẹ chúng. Phạm vi từ điển đôi khi cũng được gọi là phạm vi tĩnh .
function grandfather() {
var name = 'Hammad';
// 'likes' is not accessible here
function parent() {
// 'name' is accessible here
// 'likes' is not accessible here
function child() {
// Innermost level of the scope chain
// 'name' is also accessible here
var likes = 'Coding';
}
}
}
Điều bạn sẽ nhận thấy về phạm vi từ vựng là nó hoạt động về phía trước, có nghĩa là tên có thể được truy cập bởi bối cảnh thực thi của trẻ em. Nhưng nó không hoạt động ngược với cha mẹ của nó, có nghĩa là biến likes
này không thể được truy cập bởi cha mẹ của nó.
Điều này cũng cho chúng ta biết rằng các biến có cùng tên trong các bối cảnh thực hiện khác nhau được ưu tiên từ trên xuống dưới của ngăn xếp thực thi. Một biến, có tên tương tự với biến khác, trong hàm trong cùng (bối cảnh trên cùng của ngăn xếp thực thi) sẽ có quyền ưu tiên cao hơn.
Lưu ý rằng điều này được lấy từ đây .
Trong ngôn ngữ đơn giản, phạm vi từ vựng là một biến được xác định bên ngoài phạm vi của bạn hoặc phạm vi trên được tự động có sẵn trong phạm vi của bạn, điều đó có nghĩa là bạn không cần phải vượt qua nó ở đó.
Thí dụ:
let str="JavaScript";
const myFun = () => {
console.log(str);
}
myFun();
// Kết quả: JavaScript
bind
. Với họ, bind
không còn cần thiết nữa. Để biết thêm thông tin về thay đổi này, hãy kiểm tra stackoverflow.com/a/34361380/11127383
Có một phần quan trọng của cuộc trò chuyện xung quanh phạm vi từ vựng và động bị thiếu: một lời giải thích rõ ràng về thời gian tồn tại của biến trong phạm vi - hoặc khi biến có thể được truy cập.
Phạm vi động chỉ tương ứng rất lỏng lẻo với phạm vi "toàn cầu" theo cách mà chúng ta thường nghĩ về nó (lý do tôi đưa ra so sánh giữa hai là nó đã được đề cập - và tôi không đặc biệt thích cách giải thích của bài báo được liên kết ); có lẽ tốt nhất là chúng ta không nên so sánh giữa toàn cầu và động - mặc dù được cho là, theo bài báo được liên kết, "... [nó] hữu ích như là một thay thế cho các biến có phạm vi toàn cầu."
Vì vậy, trong tiếng Anh đơn giản, sự khác biệt quan trọng giữa hai cơ chế phạm vi là gì?
Phạm vi từ vựng đã được xác định rất rõ trong suốt các câu trả lời ở trên: các biến có phạm vi từ vựng có sẵn - hoặc, có thể truy cập - ở cấp độ cục bộ của hàm được xác định.
Tuy nhiên - vì nó không phải là trọng tâm của OP - phạm vi năng động đã không nhận được nhiều sự chú ý và sự chú ý mà nó nhận được có nghĩa là nó có thể cần thêm một chút (đó không phải là một lời chỉ trích các câu trả lời khác, mà là "oh, câu trả lời đó khiến chúng tôi ước có thêm một chút nữa "). Vì vậy, đây là một chút nữa:
Phạm vi động có nghĩa là một biến có thể truy cập được vào chương trình lớn hơn trong suốt vòng đời của lệnh gọi hàm - hoặc, trong khi hàm đang thực thi. Thực sự, Wikipedia thực sự làm một công việc tốt với lời giải thích về sự khác biệt giữa hai. Vì vậy, để không làm xáo trộn nó, đây là văn bản mô tả phạm vi động:
... [I] n phạm vi động (hoặc phạm vi động), nếu phạm vi của tên biến là một hàm nhất định, thì phạm vi của nó là khoảng thời gian trong đó hàm đang thực thi: trong khi hàm đang chạy, tên biến tồn tại và bị ràng buộc với biến của nó, nhưng sau khi hàm trả về, tên biến không tồn tại.
Phạm vi từ vựng có nghĩa là một hàm tìm kiếm các biến trong bối cảnh nơi nó được xác định và không nằm trong phạm vi ngay lập tức xung quanh nó.
Nhìn vào cách phạm vi từ vựng hoạt động trong Lisp nếu bạn muốn biết thêm chi tiết. Câu trả lời được lựa chọn của Kyle Cronin trong các biến động và biến động trong Common Lisp rõ ràng hơn nhiều so với các câu trả lời ở đây.
Thật trùng hợp, tôi chỉ học về điều này trong một lớp Lisp và nó cũng được áp dụng trong JavaScript.
Tôi đã chạy mã này trong bảng điều khiển của Chrome.
// JavaScript Equivalent Lisp
var x = 5; //(setf x 5)
console.debug(x); //(print x)
function print_x(){ //(defun print-x ()
console.debug(x); // (print x)
} //)
(function(){ //(let
var x = 10; // ((x 10))
console.debug(x); // (print x)
print_x(); // (print-x)
})(); //)
Đầu ra:
5
10
5
Phạm vi từ vựng trong JavaScript có nghĩa là một biến được xác định bên ngoài hàm có thể truy cập được bên trong hàm khác được xác định sau khai báo biến. Nhưng điều ngược lại là không đúng sự thật; các biến được định nghĩa bên trong một hàm sẽ không thể truy cập được bên ngoài hàm đó.
Khái niệm này được sử dụng nhiều trong các bao đóng trong JavaScript.
Hãy nói rằng chúng tôi có mã dưới đây.
var x = 2;
var add = function() {
var y = 1;
return x + y;
};
Bây giờ, khi bạn gọi add () -> cái này sẽ in 3.
Vì vậy, hàm add () đang truy cập vào biến toàn cục x
được xác định trước khi thêm hàm phương thức. Điều này được gọi là do phạm vi từ vựng trong JavaScript.
add()
hàm được gọi ngay sau đoạn mã đã cho, nó cũng sẽ in 3. Phạm vi từ vựng không chỉ đơn giản là hàm có thể truy cập các biến toàn cục bên ngoài ngữ cảnh cục bộ. Vì vậy, mã ví dụ thực sự không giúp thể hiện phạm vi từ vựng nghĩa là gì. Hiển thị phạm vi từ vựng trong mã thực sự cần một ví dụ ngược lại hoặc ít nhất là một lời giải thích về các cách hiểu khác về mã.
Phạm vi từ vựng đề cập đến từ vựng của mã định danh (ví dụ: biến, hàm, v.v.) hiển thị từ vị trí hiện tại trong ngăn xếp thực thi.
- global execution context
- foo
- bar
- function1 execution context
- foo2
- bar2
- function2 execution context
- foo3
- bar3
foo
và bar
luôn nằm trong từ vựng của các định danh khả dụng vì chúng là toàn cầu.
Khi function1
được thực thi, nó có quyền truy cập vào một từ vựng của foo2
, bar2
, foo
, và bar
.
Khi function2
được thực thi, nó có quyền truy cập vào một từ vựng của foo3
, bar3
, foo2
, bar2
, foo
, và bar
.
Lý do các hàm toàn cầu và / hoặc bên ngoài không có quyền truy cập vào một định danh hàm bên trong là do việc thực thi chức năng đó chưa xảy ra và do đó, không có định danh nào của nó được phân bổ vào bộ nhớ. Hơn nữa, một khi bối cảnh bên trong thực thi, nó sẽ bị xóa khỏi ngăn xếp thực thi, nghĩa là tất cả các định danh của nó đã được thu gom rác và không còn khả dụng.
Cuối cùng, đây là lý do tại sao một bối cảnh thực thi lồng nhau có thể LUÔN truy cập vào bối cảnh thực thi của tổ tiên và do đó tại sao nó có quyền truy cập vào một từ vựng lớn hơn của các định danh.
Xem:
Đặc biệt cảm ơn @ robr3rd vì đã giúp đơn giản hóa định nghĩa trên.
Đây là một góc độ khác nhau cho câu hỏi này mà chúng ta có thể nhận được bằng cách lùi lại một bước và xem xét vai trò của phạm vi trong khuôn khổ giải thích lớn hơn (chạy một chương trình). Nói cách khác, hãy tưởng tượng rằng bạn đang xây dựng một trình thông dịch (hoặc trình biên dịch) cho một ngôn ngữ và chịu trách nhiệm tính toán đầu ra, đưa ra một chương trình và một số đầu vào cho nó.
Giải thích liên quan đến việc theo dõi ba điều:
Trạng thái - cụ thể là các biến và vị trí bộ nhớ được tham chiếu trên heap và stack.
Hoạt động trên trạng thái đó - cụ thể là, mọi dòng mã trong chương trình của bạn
Các môi trường trong đó một cho hoạt động chạy - cụ thể là, các dự báo của nhà nước về phẫu thuật.
Một trình thông dịch bắt đầu ở dòng mã đầu tiên trong một chương trình, tính toán môi trường của nó, chạy dòng trong môi trường đó và nắm bắt hiệu ứng của nó đối với trạng thái của chương trình. Sau đó, nó tuân theo luồng điều khiển của chương trình để thực thi dòng mã tiếp theo và lặp lại quy trình cho đến khi chương trình kết thúc.
Cách bạn tính toán môi trường cho bất kỳ hoạt động nào là thông qua một bộ quy tắc chính thức được xác định bởi ngôn ngữ lập trình. Thuật ngữ "ràng buộc" thường được sử dụng để mô tả ánh xạ trạng thái tổng thể của chương trình tới một giá trị trong môi trường. Lưu ý rằng theo "trạng thái tổng thể", chúng tôi không có nghĩa là trạng thái toàn cầu, mà là tổng số của mọi định nghĩa có thể tiếp cận, tại bất kỳ thời điểm nào trong quá trình thực thi).
Đây là khuôn khổ trong đó vấn đề phạm vi được xác định. Bây giờ đến phần tiếp theo của những lựa chọn của chúng tôi.
Đây là ý chính của phạm vi động , trong đó môi trường mà bất kỳ mã nào chạy vào đều bị ràng buộc với trạng thái của chương trình như được xác định bởi bối cảnh thực thi của nó.
Nói cách khác, với phạm vi từ vựng , môi trường mà bất kỳ mã nào nhìn thấy đều bị ràng buộc với trạng thái được liên kết với một phạm vi được xác định rõ ràng trong ngôn ngữ, chẳng hạn như một khối hoặc một hàm.
Câu hỏi cổ xưa, nhưng đây là tôi đảm nhận nó.
Phạm vi từ vựng (tĩnh) đề cập đến phạm vi của một biến trong mã nguồn .
Trong một ngôn ngữ như JavaScript, nơi các hàm có thể được truyền qua và được gắn và gắn lại vào các đối tượng linh tinh, bạn có thể có mặc dù phạm vi đó sẽ phụ thuộc vào việc ai gọi hàm đó vào thời điểm đó, nhưng không. Thay đổi phạm vi theo cách đó sẽ là phạm vi động và JavaScript không thực hiện điều đó, ngoại trừ có thể vớithis
tham chiếu đối tượng.
Để minh họa điểm:
var a='apple';
function doit() {
var a='aardvark';
return function() {
alert(a);
}
}
var test=doit();
test();
Trong ví dụ này, biến a
được định nghĩa trên toàn cầu, nhưng bị che khuất trong doit()
hàm. Hàm này trả về một hàm khác, như bạn thấy, dựa vàoa
biến ngoài phạm vi của chính nó.
Nếu bạn chạy cái này, bạn sẽ thấy rằng giá trị được sử dụng aardvark
, không phải giá trị apple
đó, mặc dù nó nằm trong phạm vi củatest()
hàm, không nằm trong phạm vi từ vựng của hàm ban đầu. Nghĩa là, phạm vi được sử dụng là phạm vi như nó xuất hiện trong mã nguồn, không phải là phạm vi mà hàm thực sự được sử dụng.
Thực tế này có thể có hậu quả gây phiền nhiễu. Ví dụ: bạn có thể quyết định rằng việc tổ chức các chức năng của mình một cách dễ dàng hơn và sau đó sử dụng chúng khi đến lúc, chẳng hạn như trong trình xử lý sự kiện:
var a='apple',b='banana';
function init() {
var a='aardvark',b='bandicoot';
document.querySelector('button#a').onclick=function(event) {
alert(a);
}
document.querySelector('button#b').onclick=doB;
}
function doB(event) {
alert(b);
}
init();
<button id="a">A</button>
<button id="b">B</button>
Mẫu mã này làm một trong mỗi. Bạn có thể thấy rằng do phạm vi từ vựng, nút A
sử dụng biến trong, nút whileB
thì không. Bạn có thể kết thúc các chức năng lồng nhau nhiều hơn bạn muốn.
Nhân tiện, trong cả hai ví dụ, bạn cũng sẽ nhận thấy rằng các biến có phạm vi từ vựng bên trong vẫn tồn tại mặc dù hàm hàm chứa đã chạy khóa học của nó. Điều này được gọi là bao đóng và đề cập đến quyền truy cập của hàm lồng nhau vào các biến ngoài, ngay cả khi hàm ngoài đã kết thúc. JavaScript cần phải đủ thông minh để xác định xem các biến đó có còn cần thiết hay không và nếu không, rác có thể thu thập chúng hay không.
Tôi thường học bằng ví dụ, và đây là một vài điều:
const lives = 0;
function catCircus () {
this.lives = 1;
const lives = 2;
const cat1 = {
lives: 5,
jumps: () => {
console.log(this.lives);
}
};
cat1.jumps(); // 1
console.log(cat1); // { lives: 5, jumps: [Function: jumps] }
const cat2 = {
lives: 5,
jumps: () => {
console.log(lives);
}
};
cat2.jumps(); // 2
console.log(cat2); // { lives: 5, jumps: [Function: jumps] }
const cat3 = {
lives: 5,
jumps: () => {
const lives = 3;
console.log(lives);
}
};
cat3.jumps(); // 3
console.log(cat3); // { lives: 5, jumps: [Function: jumps] }
const cat4 = {
lives: 5,
jumps: function () {
console.log(lives);
}
};
cat4.jumps(); // 2
console.log(cat4); // { lives: 5, jumps: [Function: jumps] }
const cat5 = {
lives: 5,
jumps: function () {
var lives = 4;
console.log(lives);
}
};
cat5.jumps(); // 4
console.log(cat5); // { lives: 5, jumps: [Function: jumps] }
const cat6 = {
lives: 5,
jumps: function () {
console.log(this.lives);
}
};
cat6.jumps(); // 5
console.log(cat6); // { lives: 5, jumps: [Function: jumps] }
const cat7 = {
lives: 5,
jumps: function thrownOutOfWindow () {
console.log(this.lives);
}
};
cat7.jumps(); // 5
console.log(cat7); // { lives: 5, jumps: [Function: thrownOutOfWindow] }
}
catCircus();
Chủ đề này liên quan chặt chẽ với bind
chức năng tích hợp và được giới thiệu trong Chức năng mũi tên ECMAScript 6 . Điều đó thực sự gây phiền nhiễu, bởi vì đối với mọi phương thức "lớp" (hàm thực sự) mới mà chúng tôi muốn sử dụng, chúng tôi phải thực hiện bind
điều này để có quyền truy cập vào phạm vi.
JavaScript theo mặc định không đặt phạm vi this
chức năng của nó (nó không đặt bối cảnh trên this
). Theo mặc định, bạn phải nói rõ ràng bối cảnh bạn muốn có.
Các hàm mũi tên tự động được gọi là phạm vi từ vựng (có quyền truy cập vào định nghĩa của biến trong khối chứa của nó). Khi sử dụng các chức năng mũi tên, nó sẽ tự động liên kết this
đến vị trí nơi chức năng mũi tên được xác định ở vị trí đầu tiên và bối cảnh của chức năng mũi tên này này là khối chứa.
Xem cách nó hoạt động trong thực tế trên các ví dụ đơn giản nhất dưới đây.
Trước Hàm mũi tên (không có phạm vi từ vựng theo mặc định):
const programming = {
language: "JavaScript",
getLanguage: function() {
return this.language;
}
}
const globalScope = programming.getLanguage;
console.log(globalScope()); // Output: undefined
const localScope = programming.getLanguage.bind(programming);
console.log(localScope()); // Output: "JavaScript"
Với các hàm mũi tên (phạm vi từ vựng theo mặc định):
const programming = {
language: "JavaScript",
getLanguage: function() {
return this.language;
}
}
const arrowFunction = () => {
console.log(programming.getLanguage());
}
arrowFunction(); // Output: "JavaScript"