Văn hay trong hiện tại, chữ tốt ở tương lai

Bạn chưa biết rõ về JavaScript đâu (You don't know JS yet) | Chương 2.2

Khám phá bản chất JavaScript từ lịch sử tên gọi, chuẩn ECMAScript và tính đa mô thức. Xóa bỏ lầm tưởng, xây nền tảng vững chắc cho nhà phát triển website.

25 phút đọc.

0 lượt xem.

Mở đầu

Trong những chương trước, chúng ta đã tiến hành khám phá cách thức mà phạm vi của một chương trình được hệ thống định hình và thiết lập ngay trong giai đoạn biên dịch mã nguồn, một mô hình kiến trúc nền tảng được giới khoa học máy tính gọi tên là phạm vi từ vựng. Thuật ngữ từ vựng ở đây có mối liên hệ trực tiếp và trỏ thẳng đến giai đoạn đầu tiên của toàn bộ quy trình biên dịch, tức là giai đoạn phân tích từ vựng và phân tích cú pháp. Để có thể thực sự lập luận và tư duy một cách chuẩn xác về các chương trình phần mềm mà chúng ta viết ra, điều kiện tiên quyết mang tính bắt buộc là người kỹ sư phải xây dựng được một nền tảng nhận thức khái niệm vô cùng vững chắc về cách thức mà phạm vi vận hành trong thực tế. Nếu chúng ta chỉ đơn thuần dựa dẫm vào những phỏng đoán mơ hồ hay trực giác cá nhân, có thể đôi khi chúng ta sẽ may mắn vô tình đạt được những kết quả đúng đắn, nhưng trong vô số những tình huống phức tạp khác, những suy luận đó sẽ đưa chúng ta đi chệch hướng hoàn toàn xa rời bản chất vấn đề. Sự mơ hồ này chắc chắn không bao giờ là một công thức hoàn hảo dẫn đến sự thành công bền vững trong kỹ thuật lập trình. Giống hệt như những bài học toán học cơ bản thời trung học, việc chỉ đưa ra được một đáp án cuối cùng chính xác là hoàn toàn chưa đủ nếu như chúng ta không thể trình bày và chứng minh được các bước giải quyết vấn đề một cách logic để đi đến được đáp án đó. Nhiệm vụ cấp bách của chúng ta là phải tự tay kiến tạo nên những mô hình tư duy chính xác và hữu ích nhằm làm nền tảng vững chãi cho những bước tiến xa hơn trong tương lai.

Hình tượng hóa phạm vi từ vựng và cơ chế phân giải định danh

Chương tài liệu này sẽ tiến hành minh họa và cụ thể hóa khái niệm phạm vi thông qua việc sử dụng một loạt các phép ẩn dụ mang tính trực quan cao độ. Mục tiêu tối thượng của phương pháp tiếp cận này là nhằm uốn nắn và rèn luyện cách thức mà bạn tư duy về quá trình hệ thống JavaScript xử lý chương trình, sao cho luồng suy nghĩ đó ngày càng trở nên đồng điệu và bám sát nhất với những cơ chế vận hành thực tế đang diễn ra bên dưới cỗ máy thông dịch.

Mô hình phân loại biến số thông qua màu sắc và ranh giới không gian

Một trong những phép ẩn dụ vô cùng hữu hiệu và mang lại giá trị nhận thức cao nhất để thấu hiểu khái niệm phạm vi là hình ảnh phân loại những viên bi ve đầy màu sắc vào trong những chiếc xô có màu sắc tương ứng với chúng. Hãy thử nhắm mắt lại và tưởng tượng rằng bạn đang đứng trước một đống bi ve khổng lồ, và bạn tinh ý nhận ra rằng tất cả những viên bi này đều mang trên mình một trong ba màu sắc cơ bản: màu đỏ, màu xanh dương, hoặc màu xanh lá cây. Nhiệm vụ của chúng ta là tiến hành phân loại toàn bộ đống bi ve lộn xộn đó, cẩn thận thả những viên bi màu đỏ vào bên trong một chiếc xô màu đỏ, những viên bi màu xanh lá cây vào một chiếc xô màu xanh lá cây, và tương tự, những viên bi màu xanh dương sẽ được gom gọn vào chiếc xô màu xanh dương. Sau khi quá trình phân loại khắt khe này hoàn tất, nếu tại một thời điểm nào đó trong tương lai bạn đột nhiên cần đến một viên bi màu xanh lá cây, bạn đã nắm chắc trong đầu thông tin rằng chiếc xô màu xanh lá cây chính là địa điểm duy nhất và chính xác nhất mà bạn cần tìm đến để lấy được nó. Trong bức tranh ẩn dụ trực quan này, những viên bi ve đóng vai trò đại diện cho các biến số tồn tại bên trong chương trình phần mềm của chúng ta. Tương ứng với đó, những chiếc xô chính là hiện thân của các không gian phạm vi (có thể là phạm vi của một hàm điện toán hoặc phạm vi của một khối mã lệnh), mà vì mục đích phục vụ cho cuộc thảo luận này, chúng ta đã chủ động gán cho chúng những màu sắc riêng biệt để dễ dàng nhận diện. Dựa trên quy tắc đó, màu sắc của từng viên bi ve riêng lẻ sẽ được quyết định hoàn toàn bởi việc chúng ta phát hiện ra viên bi đó ban đầu được khai sinh và tạo ra bên trong cái không gian phạm vi mang màu sắc nào. Sự ánh xạ một-một giữa nơi khởi tạo và danh tính của biến số này giúp đảm bảo rằng quá trình tra cứu sau này luôn diễn ra một cách có tính toán và dự đoán được.

Để có thể đi sâu hơn vào bản chất kỹ thuật, chúng ta hãy cùng nhau phân tích và gắn nhãn màu sắc phạm vi cho một ví dụ chương trình đã được đề cập từ chương trước. Trong chương trình này, chúng ta có thể phân định rõ ràng ba màu sắc phạm vi thông qua các dòng chú thích trong mã nguồn: phạm vi bao bọc toàn cục ngoài cùng sẽ được khoác lên mình màu đỏ, phạm vi bên trong của một hàm điện toán lấy tên sinh viên sẽ mang màu xanh dương, và cuối cùng, không gian phạm vi cục bộ nằm gọn bên trong một vòng lặp sẽ được đặc trưng bởi màu xanh lá cây. Mặc dù đã có sự phân định rõ ràng như vậy, nhưng đôi khi người lập trình vẫn có thể gặp phải những khó khăn nhất định trong việc nhận diện bằng mắt thường các đường ranh giới của những chiếc xô phạm vi này khi chỉ nhìn chằm chằm vào một đoạn mã văn bản thuần túy. Để giải quyết trở ngại thị giác này, chúng ta có thể sử dụng biểu đồ để trực quan hóa các ranh giới phạm vi bằng cách vẽ những bong bóng (hay những chiếc xô) bao quanh từng khu vực: bong bóng màu đỏ số một sẽ ôm trọn lấy toàn bộ phạm vi toàn cục, nơi nắm giữ ba định danh biến số bao gồm một mảng danh sách sinh viên, một hàm lấy tên, và một biến sinh viên tiếp theo. Bong bóng màu xanh dương số hai sẽ bao bọc không gian bên trong của hàm lấy tên, chứa đựng duy nhất một định danh là tham số đầu vào của hàm đó. Cuối cùng, bong bóng màu xanh lá cây số ba sẽ khoanh vùng phạm vi của vòng lặp, quản lý một biến số cục bộ duy nhất đại diện cho từng sinh viên trong mỗi chu kỳ lặp. Những bong bóng phạm vi này được hệ thống xác định một cách tuyệt đối ngay trong quá trình biên dịch, dựa trên vị trí vật lý mà các hàm hay khối mã được viết ra, cũng như mức độ lồng ghép của chúng vào nhau. Một nguyên tắc kiến trúc bất di bất dịch là mỗi một bong bóng phạm vi luôn luôn được chứa đựng trọn vẹn bên trong bong bóng phạm vi cha của nó – tuyệt đối không bao giờ có hiện tượng một không gian phạm vi lại tồn tại một cách lơ lửng, vắt ngang và chia sẻ một phần cơ thể của nó cho hai không gian phạm vi bao bọc hoàn toàn khác biệt nhau.

Mỗi một viên bi ve (hay biến số định danh) sẽ được hệ thống tô màu dựa trên việc nó được tuyên bố khai báo bên trong chiếc xô (hay bong bóng) nào, chứ hoàn toàn không phụ thuộc vào màu sắc của không gian phạm vi nơi mà biến số đó có thể bị truy cập và gọi đến sau này. Khi cỗ máy JavaScript xử lý một chương trình (trong suốt giai đoạn biên dịch) và bắt gặp một câu lệnh khai báo cho một biến số, về bản chất nó sẽ tự đặt ra một câu hỏi định hướng: Hiện tại tôi đang đứng bên trong không gian phạm vi (chiếc xô hay bong bóng) mang màu sắc nào?. Ngay lập tức, biến số đó sẽ được hệ thống gán cho đúng cái màu sắc tương ứng đó, đồng nghĩa với việc nó chính thức thuộc về quyền sở hữu của chiếc xô hay bong bóng đó. Xét theo cấu trúc lồng ghép, chiếc xô màu xanh lá cây nằm gọn hoàn toàn bên trong lòng của chiếc xô màu xanh dương, và tương tự như một con búp bê Nga, chiếc xô màu xanh dương lại nằm nép mình trọn vẹn bên trong chiếc xô màu đỏ khổng lồ. Các không gian phạm vi có khả năng lồng ghép vào nhau theo cấu trúc như vậy, tiến sâu đến bất kỳ một mức độ phức tạp nào mà kiến trúc chương trình của bạn đòi hỏi. Đối với các hành vi tham chiếu biến số (không phải là những câu lệnh khai báo), hệ thống chỉ cấp phép truy cập nếu như nó tìm thấy một khai báo trùng khớp nằm ngay tại phạm vi hiện hành, hoặc nằm ở bất kỳ một không gian phạm vi nào ở tầng cao hơn hay bao bọc bên ngoài phạm vi hiện tại; thế nhưng, hệ thống nghiêm cấm tuyệt đối việc tham chiếu đến các khai báo nằm ở những không gian phạm vi thấp hơn hoặc bị lồng ghép sâu hơn ở bên trong. Điều này có nghĩa là một biểu thức nằm ở chiếc xô màu đỏ chỉ được quyền chạm vào các viên bi màu đỏ, chứ tuyệt đối không thể với tới các viên bi màu xanh dương hay xanh lá cây. Ngược lại, một biểu thức ngụ tại chiếc xô màu xanh lá cây lại có đặc quyền truy xuất vào toàn bộ kho tàng bi ve bao gồm màu đỏ, màu xanh dương và cả màu xanh lá cây. Quá trình tra cứu màu sắc của những viên bi không mang tính chất khai báo này có thể được hình dung như một cuộc tìm kiếm tuần tự: nếu chiếc xô hiện tại không có viên bi mang tên đó, hệ thống sẽ tiếp tục nâng bước sang chiếc xô bao bọc bên ngoài tiếp theo để tìm kiếm, và cứ thế tiếp diễn cho đến khi tìm thấy sự trùng khớp. Mặc dù chúng ta sử dụng hình ảnh cuộc tra cứu tại thời gian chạy như một thủ pháp tu từ để dễ hình dung, nhưng thực tế tinh vi hơn rất nhiều: trong giai đoạn biên dịch, hệ thống đã nỗ lực khớp nối hầu hết mọi tham chiếu biến số với những chiếc xô phạm vi đã được xác định trước, từ đó lưu trữ sẵn màu sắc cho từng viên bi nhằm mục đích né tránh tối đa những cuộc tra cứu lặp đi lặp lại không cần thiết khi chương trình bước vào vận hành thực tế.

Cuộc hội thoại nội bộ và cơ chế xác định vai trò của biến số

Một phương pháp ẩn dụ khác không kém phần sâu sắc và hữu dụng để mổ xẻ quá trình phân tích các biến số cũng như nguồn gốc không gian phạm vi của chúng là việc chúng ta hãy thử tưởng tượng ra những cuộc hội thoại giả định diễn ra liên tục bên trong cỗ máy thông dịch khi mã nguồn đang được xử lý và sau đó là thực thi. Bằng cách nghe lén những cuộc trao đổi nội bộ này, chúng ta sẽ xây dựng được một nền móng khái niệm vững chãi hơn rất nhiều về cơ chế hoạt động của các không gian phạm vi. Hãy cùng nhau làm quen với bộ ba nhân vật cộm cán cấu thành nên hệ thống JavaScript, những người sẽ trực tiếp tham gia vào các cuộc đàm thoại khi họ chung tay xử lý chương trình của chúng ta. Nhân vật trung tâm là Cỗ máy, người gánh vác trách nhiệm bao quát từ lúc khởi đầu cho đến khi kết thúc toàn bộ quy trình biên dịch và thi hành mã lệnh. Đồng hành cùng Cỗ máy là một người bạn đắc lực mang tên Trình biên dịch, người thầu toàn bộ những công việc nặng nhọc liên quan đến việc phân tích cú pháp và kiến tạo ra mã máy. Nhân vật thứ ba, không kém phần quan trọng, là Người quản lý phạm vi, một cộng sự thân thiết khác của Cỗ máy; nhiệm vụ của người này là miệt mài thu thập, xây dựng và bảo trì một danh sách tra cứu chứa đựng toàn bộ các biến số và định danh đã được khai báo, đồng thời đóng vai trò như một cảnh sát thực thi một bộ quy tắc nghiêm ngặt quy định cách thức mà các mã lệnh đang chạy được quyền truy cập vào danh sách này. Để có thể đạt đến cảnh giới thấu hiểu tường tận mọi ngóc ngách của hệ thống, bạn bắt buộc phải bắt đầu tập suy nghĩ giống hệt như cách mà Cỗ máy cùng những người bạn của nó tư duy, phải học cách đặt ra những câu hỏi mà họ thường thắc mắc, và tự mình đưa ra những câu trả lời theo đúng logic của họ.

Để khám phá sâu hơn vào những cuộc hội thoại này, hãy cùng nhìn lại ví dụ chương trình quen thuộc với danh sách sinh viên. Chúng ta sẽ tiến hành soi xét cách thức hệ thống chuẩn bị xử lý đoạn chương trình đó, mà cụ thể là sẽ mổ xẻ ngay từ câu lệnh đầu tiên khai báo mảng sinh viên. Tư duy thông thường của con người thường có xu hướng gộp chung việc khai báo và gán giá trị lại thành một câu lệnh duy nhất, nhưng đó hoàn toàn không phải là cách mà người bạn Cỗ máy của chúng ta nhìn nhận vấn đề. Trên thực tế kiến trúc, hệ thống JavaScript chia tách câu lệnh đó thành hai thao tác kỹ thuật hoàn toàn biệt lập với nhau: một thao tác sẽ do Trình biên dịch đích thân xử lý ngay trong giai đoạn biên dịch tĩnh, và thao tác còn lại sẽ được bàn giao cho Cỗ máy gánh vác trong suốt quá trình thực thi động. Nhiệm vụ đầu tiên mà Trình biên dịch phải làm với chương trình này là tiến hành phân tích từ vựng để băm nhỏ nó ra thành các thẻ từ, sau đó tiếp tục nhào nặn những thẻ từ đó thành một cấu trúc cây cú pháp trừu tượng. Khi Trình biên dịch bước vào giai đoạn kiến tạo mã máy, có rất nhiều chi tiết tinh vi cần phải được cân nhắc kỹ lưỡng hơn so với những gì thể hiện trên bề mặt. Một giả định có vẻ hợp lý nhưng lại thiếu xót là Trình biên dịch sẽ đẻ ra một đoạn mã cho câu lệnh đầu tiên với nội dung kiểu như: Hãy cấp phát một vùng nhớ cho một biến số, dán nhãn cho nó là danh sách sinh viên, rồi sau đó nhét sợi dây tham chiếu trỏ đến mảng dữ liệu vào trong cái biến số đó.. Tuy nhiên, đó vẫn chưa phải là toàn bộ bức tranh sự thật. Thực tế, Trình biên dịch sẽ vạch ra những bước đi cụ thể: khi chạm trán với từ khóa khai báo biến, nó sẽ cất tiếng hỏi Người quản lý phạm vi xem liệu đã có một biến số nào mang tên như vậy tồn tại sẵn trong chiếc xô phạm vi cụ thể đó hay chưa. Nếu câu trả lời là có, Trình biên dịch sẽ phớt lờ khai báo này và lạnh lùng bước tiếp. Trong trường hợp ngược lại, nó sẽ sản sinh ra một đoạn mã để yêu cầu Người quản lý phạm vi khởi tạo một biến số hoàn toàn mới mang tên đó ngay trong chiếc xô phạm vi tương ứng. Tiếp nối sau đó, Trình biên dịch mới bắt đầu đẻ ra đoạn mã dành cho Cỗ máy thi hành sau này, nhằm mục đích xử lý thao tác gán mảng dữ liệu. Đoạn mã mà Cỗ máy thi hành sẽ mở đầu bằng việc chất vấn Người quản lý phạm vi xem có biến số nào mang tên đó đang hiện diện và có thể chạm tới được trong chiếc xô phạm vi hiện tại hay không. Nếu không tìm thấy, Cỗ máy sẽ kiên trì lùng sục ở những nơi khác, và một khi đã tóm được mục tiêu, nó mới tiến hành gán sợi dây tham chiếu của mảng dữ liệu vào biến số đó.

Nếu chuyển thể quá trình này thành một cuộc hội thoại, giai đoạn biên dịch đầu tiên của chương trình giữa Trình biên dịchNgười quản lý phạm vi sẽ diễn ra dưới hình thức những câu hỏi đáp liên tục. Trình biên dịch liên tục thông báo về việc tìm thấy các khai báo định danh chính thức và hỏi xem Người quản lý phạm vi đã từng nghe danh về chúng hay chưa. Nếu nhận được cái lắc đầu từ chối, Người quản lý phạm vi sẽ ngay lập tức khởi tạo biến số đó trong phạm vi quản lý của mình. Trình biên dịch cũng phát tín hiệu cảnh báo mỗi khi nó băng qua các hàm hoặc các khối phạm vi, để từ đó hệ thống có thể đẻ ra một chiếc xô phạm vi mới toanh kèm theo một Người quản lý phạm vi được phân công phụ trách riêng cho khu vực đó. Kéo theo sau đó, khi dòng thời gian trôi đến giai đoạn thực thi chương trình, bối cảnh cuộc hội thoại sẽ ngay lập tức được chuyển giao cho Cỗ máyNgười quản lý phạm vi. Cuộc đàm thoại này lại tiếp tục là một chuỗi các màn hỏi đáp căng thẳng: Cỗ máy sẽ yêu cầu Người quản lý phạm vi tìm kiếm các định danh đã được hệ thống kéo lên từ trước để tiến hành gán các hàm vào đó, tiếp theo nó lại hỏi han về các tham chiếu đóng vai trò là đích đến cho các biến số, yêu cầu truy xuất chúng để khởi tạo giá trị trống chuẩn bị cho việc sử dụng, và cuối cùng mới tiến hành gán các giá trị dữ liệu thực sự vào chúng. Việc nắm bắt được nhịp điệu của những cuộc hội thoại này là chìa khóa vàng để thấu hiểu cách thức ngôn ngữ phân định rạch ròi giữa nhiệm vụ thiết lập cấu trúc tĩnh và việc thi hành các thao tác động.

Kiến trúc lồng ghép phạm vi và các hệ lụy từ quá trình tra cứu thất bại

Khi thời khắc chín muồi để hệ thống tiến hành thực thi hàm lấy tên sinh viên, Cỗ máy sẽ phát lệnh yêu cầu cung cấp một phiên bản Người quản lý phạm vi được thiết kế riêng biệt cho không gian phạm vi của cái hàm đó, và nó sẽ tuần tự tiến hành tra cứu tham số đầu vào nhằm mục đích gán giá trị đối số được truyền vào, và cứ thế tiếp tục chu trình. Phân tích về mặt cấu trúc không gian, phạm vi của hàm điện toán này nằm lọt thỏm hoàn toàn bên trong không gian phạm vi toàn cục. Tương tự như vậy, phạm vi khối của vòng lặp cũng nằm nép mình một cách hoàn hảo bên trong không gian phạm vi của cái hàm đó. Các không gian phạm vi sở hữu khả năng lồng ghép từ vựng vào nhau tiến tới bất kỳ một độ sâu trừu tượng nào mà bản thân kiến trúc chương trình đã vạch ra. Mỗi một không gian phạm vi sẽ được vinh dự nhận riêng một phiên bản Người quản lý phạm vi mỗi khi phạm vi đó bị đánh thức và gọi thi hành (có thể là một lần hoặc lặp lại hàng triệu lần). Một đặc quyền ma thuật là mỗi không gian phạm vi đều tự động sở hữu toàn bộ các định danh của nó được đăng ký đầy đủ ngay tại vạch xuất phát khi phạm vi đó bắt đầu chạy (đây chính là hiện tượng kéo lên của biến số). Nếu bất kỳ một định danh nào có nguồn gốc xuất thân từ một khai báo hàm, thì tại điểm khởi đầu của không gian phạm vi, biến số đó sẽ tự động được hệ thống khởi tạo và kết nối với sợi dây tham chiếu hàm tương ứng của nó. Và nếu định danh đó ra đời từ một từ khóa khai báo biến truyền thống, biến số đó sẽ tự động được khởi tạo với một giá trị trống rỗng để luôn trong tư thế sẵn sàng được sử dụng; nếu không, biến số đó sẽ bị kẹt lại ở trạng thái chưa được khởi tạo và tuyệt đối không thể bị đụng chạm tới cho đến khi toàn bộ câu lệnh khai báo và khởi tạo của nó được hệ thống thi hành trọn vẹn.

Trong quá trình lặp, khi bắt gặp một biến số đóng vai trò là nguồn phát cần phải được tra cứu để lấy dữ liệu, làm thế nào hệ thống giải quyết bài toán này khi mà không gian phạm vi cục bộ của hàm hoàn toàn không chứa đựng bất kỳ thông tin nào về định danh đó? Để làm sáng tỏ vấn đề này, hãy mường tượng đoạn hội thoại giải quyết khủng hoảng: Cỗ máy thông báo về việc sở hữu một tham chiếu nguồn phát và hỏi Người quản lý phạm vi của hàm xem có biết nó không. Nhận được lời phủ nhận và gợi ý hãy thử vận may ở không gian phạm vi bao bọc bên ngoài tiếp theo, Cỗ máy sẽ ngoan ngoãn trèo lên và hỏi Người quản lý phạm vi toàn cục, và tại đây, nó nhận được cái gật đầu xác nhận vì biến số đó đã được khai báo chính thức ở cấp độ này. Một trong những nguyên lý vận hành mang tính rường cột của cơ chế phạm vi từ vựng là: bất cứ khi nào một nỗ lực tham chiếu định danh bị thất bại do không thể tìm thấy trong không gian phạm vi hiện tại, hệ thống sẽ tự động chuyển hướng và tham vấn không gian phạm vi bao bọc bên ngoài gần nhất trong cấu trúc lồng ghép; tiến trình trèo rào này sẽ lặp đi lặp lại một cách nhẫn nại cho đến khi tìm được lời giải đáp thỏa đáng hoặc cho đến khi cạn kiệt toàn bộ các không gian phạm vi có thể thỉnh thị. Khi Cỗ máy đã vắt kiệt mọi không gian phạm vi có sẵn về mặt từ vựng (bằng cách di chuyển liên tục ra phía ngoài) mà vẫn hoàn toàn bất lực trong việc phân giải truy vấn của một định danh, thì một tình trạng lỗi nghiêm trọng sẽ chính thức được kích hoạt. Tuy nhiên, phương thức xử lý tình trạng lỗi này sẽ biến thiên đa dạng phụ thuộc vào chế độ vận hành hiện tại của chương trình (có đang ở chế độ nghiêm ngặt hay không) cũng như vai trò cụ thể của cái biến số đang gây rắc rối đó (là đích đến hay nguồn phát).

Nếu biến số đóng vai trò là một nguồn phát, một cuộc tra cứu định danh bất thành sẽ bị hệ thống kết tội là một hành vi sử dụng biến số chưa từng được khai báo (tức là biến số vô danh, hoặc mất tích), và tội danh này luôn luôn bị trừng phạt bằng cách ném ra một Lỗi Tham Chiếu khốc liệt làm sập chương trình. Thêm vào đó, nếu biến số đó mang vai trò là một đích đến, và đoạn mã tại khoảnh khắc đó đang bị trói buộc bởi các quy tắc của chế độ nghiêm ngặt, thì biến số đó cũng chịu chung số phận bị kết án là chưa được khai báo và nhận về một Lỗi Tham Chiếu tương tự. Thông điệp báo lỗi dành cho tình trạng biến chưa được khai báo trên hầu hết các môi trường thực thi sẽ có hình hài đại loại như: Lỗi Tham Chiếu: XYZ chưa được định nghĩa. Cụm từ chưa được định nghĩa thoạt nghe có vẻ giống hệt như một giá trị trống rỗng trong hệ thống ngôn ngữ, nhưng trên bình diện kỹ thuật của ngôn ngữ này, hai khái niệm này là hoàn toàn biệt lập và khác biệt nhau một trời một vực, và thông điệp báo lỗi tai hại này vô tình gieo rắc một sự nhầm lẫn dai dẳng và ám ảnh trong cộng đồng lập trình. Chưa được định nghĩa về bản chất sâu xa mang ý nghĩa là chưa được khai báo – tức là ám chỉ một biến số hoàn toàn không sở hữu bất kỳ một lời khai báo chính thức nào trùng khớp với nó ở trong toàn bộ mọi không gian phạm vi có sẵn về mặt từ vựng. Trái ngược hoàn toàn, một giá trị trống rỗng mang hàm ý rằng hệ thống đã tìm thấy và công nhận sự tồn tại của biến số đó (nó đã được khai báo đàng hoàng), nhưng bản thân cái biến số đó tại thời điểm bị tra cứu lại không chứa đựng bất kỳ một giá trị dữ liệu nào bên trong, nên hệ thống buộc phải để nó thoái lui về giá trị mặc định là trống rỗng. Và để đẩy sự hỗn loạn của các thuật ngữ lên đến tột đỉnh, toán tử kiểm tra kiểu dữ liệu của ngôn ngữ này lại thản nhiên trả về một chuỗi văn bản trống rỗng cho các tham chiếu biến số đang nằm ở bất kỳ trạng thái nào trong hai trạng thái tồi tệ kể trên. Khủng khiếp hơn nữa, nếu biến số đóng vai trò là một đích đến và hệ thống đang lơ đễnh hoạt động bên ngoài chế độ nghiêm ngặt, một hành vi di sản vô cùng khó hiểu và đầy rẫy sự ngạc nhiên sẽ bị kích hoạt: hệ quả tai hại là Người quản lý phạm vi toàn cục sẽ tự động lộng quyền và tạo ra một biến số toàn cục do tai nạn chỉ để chiều chuộng và hoàn tất cho bằng được cái thao tác gán nhắm vào đích đến đó! Đây chính là minh chứng hùng hồn nhất cho tầm quan trọng sống còn của việc sử dụng chế độ nghiêm ngặt để bảo vệ sự toàn vẹn của mã nguồn khỏi những quyết định tự động ngu ngốc của hệ thống cũ.

Kết luận

Khi đi đến những dòng chữ này, tâm trí của bạn hẳn đã bắt đầu nhào nặn và phát triển được những mô hình tư duy phong phú, đa chiều và chính xác hơn rất nhiều về bản chất thực sự của phạm vi, cũng như thấu hiểu cặn kẽ cách thức mà cỗ máy thông dịch nhận diện và khai thác cơ chế này trực tiếp từ các đoạn mã nguồn do bạn viết ra. Trước khi tiếp tục dấn thân vào những chương kiến thức phức tạp hơn, một bài tập thực hành mang tính sống còn là bạn hãy tự mình đi lùng sục một vài đoạn mã trong các dự án thực tế của bản thân và thử đóng vai, chạy lại các cuộc hội thoại giả định này trong đầu. Hãy thực sự đọc to những câu thoại đó lên, hoặc tìm một người đồng nghiệp để cùng nhau diễn tập từng vai trò một, bởi vì việc nói ra thành lời sẽ giúp củng cố tư duy logic một cách kỳ diệu. Nếu trong quá trình diễn tập, bất kỳ ai trong số các bạn cảm thấy lúng túng, bối rối hay bị vấp váp trong dòng suy luận, điều đó chứng tỏ nền tảng của bạn chưa thực sự vững chắc, và bạn bắt buộc phải đầu tư thêm thời gian để nghiền ngẫm lại toàn bộ khối lượng tài liệu này. Chỉ khi đã hoàn toàn làm chủ được những khái niệm vi mô này, chúng ta mới có đủ hành trang để tự tin bước lên (hoặc bước ra) chương tiếp theo, nơi chúng ta sẽ khám phá cách thức những không gian phạm vi từ vựng này móc nối và liên kết với nhau để tạo thành một chuỗi xích khổng lồ điều khiển luồng dữ liệu của toàn bộ chương trình.

Chuyên mục chua-biet-javascript

Theo dõi hành trình

Hãy để lại thông tin, khi có gì mới thì Nhà văn sẽ gửi thư đến bạn để cập nhật. Cam kết không gửi email rác.

Họ và tên

Email liên lạc

Đôi dòng chia sẻ