Javascript là một thảm họa

Nút. js đã trở thành một trong những nền tảng phổ biến nhất trong vài năm qua. Chắc chắn là dễ dàng để bắt đầu với các Node đó. js, nhưng một khi bạn vượt qua ứng dụng

"engines": {
  "node": "6.2.0"
}
4 cơ bản, biết cách cấu trúc tốt nhất mã của bạn và cách xử lý lỗi đôi khi có thể trở thành cơn ác mộng (như với hầu hết các ngôn ngữ và khuôn khổ)

Và thật không may, cơn ác mộng đó tạo ra sự khác biệt giữa một ứng dụng sản xuất vững chắc và một thảm họa phóng

Như đã nói, chúng ta hãy xem một số Node tốt nhất. js sẽ giúp bạn an toàn trước Node phổ biến nhất. bẫy js

1. Bắt đầu tất cả các dự án với "engines": { "node": "6.2.0" } 5

Hầu hết mọi người đều quen thuộc với NPM như một cách để cài đặt các phụ thuộc, nhưng nó còn nhiều hơn thế nữa. Đầu tiên, tôi thực sự khuyên bạn nên tạo một dự án mới bằng cách sử dụng

"engines": {
  "node": "6.2.0"
}
5, như vậy

$ mkdir my-new-project
$ cd my-new-project
$ npm init

Thao tác này sẽ tạo một

"engines": {
  "node": "6.2.0"
}
7 mới cho bạn, cho phép bạn thêm một loạt siêu dữ liệu để giúp những người khác đang làm việc trong dự án có cùng thiết lập với bạn

Ví dụ: tôi thường mở

"engines": {
  "node": "6.2.0"
}
7 và thêm một phiên bản cụ thể của Node. js tôi định chạy tiếp, bằng cách thêm

"engines": {
  "node": "6.2.0"
}

2. Thiết lập "engines": { "node": "6.2.0" } 9

Nếu bạn đã sử dụng npm trước đây, bạn có thể đã bắt gặp cờ

$ npm config set save=true
$ npm config set save-exact=true
0 cập nhật
"engines": {
  "node": "6.2.0"
}
7 với phần phụ thuộc. Khi các nhà phát triển khác sao chép dự án, họ có thể chắc chắn có các phụ thuộc phù hợp vì điều này. Thật không may, việc nhớ thêm cờ có thể là một vấn đề

Ngoài ra, NPM thêm dấu nháy đầu tiên

$ npm config set save=true
$ npm config set save-exact=true
2 cho tất cả các phiên bản. Do đó, khi ai đó chạy
$ npm config set save=true
$ npm config set save-exact=true
3, họ có thể nhận được các phiên bản mô-đun khác với phiên bản bạn có. Mặc dù cập nhật các mô-đun luôn là một phương pháp hay, nhưng việc có một nhóm các nhà phát triển chạy trên các phiên bản phụ thuộc hơi khác nhau có thể dẫn đến sự khác biệt về hành vi hoặc tính khả dụng của API

Do đó, nên để mọi người sử dụng cùng một phiên bản. Để làm điều này dễ dàng hơn cho mọi người, tệp

"engines": {
  "node": "6.2.0"
}
9 có một số thuộc tính hữu ích có thể đảm bảo rằng
$ npm config set save=true
$ npm config set save-exact=true
3 luôn cập nhật
"engines": {
  "node": "6.2.0"
}
7 và thực thi phiên bản phụ thuộc đã cài đặt phải khớp chính xác

Chỉ cần chạy các dòng sau trong thiết bị đầu cuối của bạn

________số 8

Bây giờ khi bạn chạy

$ npm config set save=true
$ npm config set save-exact=true
3, bạn có thể chắc chắn rằng phần phụ thuộc đã được lưu và sẽ bị khóa đối với phiên bản bạn đã cài đặt

3. Thêm tập lệnh vào "engines": { "node": "6.2.0" } 7 của bạn

Nếu có một thứ mà tất cả các ứng dụng đều cần, thì đó là một tập lệnh khởi chạy. Biết nên gọi tệp nào trước và với những đối số nào có thể là một cuộc phiêu lưu khám phá hoành tráng trong một số dự án. Điều tốt là NPM có một cách tiêu chuẩn để bắt đầu tất cả các ứng dụng nút

Chỉ cần thêm thuộc tính và đối tượng

$ npm config set save=true
$ npm config set save-exact=true
9 vào
"engines": {
  "node": "6.2.0"
}
7 của bạn bằng khóa
"engines": {
  "node": "6.2.0"
}
01. Giá trị của nó phải là lệnh khởi chạy ứng dụng của bạn. Ví dụ

"engines": {
  "node": "6.2.0"
}
0

Ngay khi ai đó chạy

"engines": {
  "node": "6.2.0"
}
02, NPM sẽ chạy
"engines": {
  "node": "6.2.0"
}
03 với tất cả các phụ thuộc từ
"engines": {
  "node": "6.2.0"
}
04 trên
"engines": {
  "node": "6.2.0"
}
05 của bạn. Điều này có nghĩa là bạn có thể tránh phải cài đặt toàn cầu các mô-đun NPM

Có một vài móc nối kịch bản khác đáng để biết

"engines": {
  "node": "6.2.0"
}
6

Tập lệnh

"engines": {
  "node": "6.2.0"
}
06 được chạy sau khi chạy
$ npm config set save=true
$ npm config set save-exact=true
3. Ngoài ra còn có
"engines": {
  "node": "6.2.0"
}
08 nếu bạn cần chạy thứ gì đó trước khi tất cả các phụ thuộc NPM được cài đặt

Tập lệnh

"engines": {
  "node": "6.2.0"
}
09 được chạy khi ai đó chạy
"engines": {
  "node": "6.2.0"
}
60. Đây là một cách đơn giản hay để ai đó có thể chạy thử nghiệm của bạn mà không cần biết liệu bạn có chọn sử dụng Jasmine, Mocha, Selenium, v.v.

Bạn cũng có thể thêm các tập lệnh tùy chỉnh của riêng mình tại đây. Sau đó, chúng có thể được chạy bằng cách sử dụng

"engines": {
  "node": "6.2.0"
}
61 — một cách đơn giản để bạn cung cấp cho nhóm của mình một tập lệnh khởi chạy trung tâm

4. Sử dụng biến môi trường

Quản lý cấu hình luôn là một chủ đề lớn trong bất kỳ ngôn ngữ nào. Làm cách nào để bạn tách mã của mình khỏi cơ sở dữ liệu, dịch vụ, v.v. mà nó phải sử dụng trong quá trình phát triển, QA và sản xuất?

Cách được đề xuất trong Node. js là sử dụng các biến môi trường và tra cứu các giá trị từ

"engines": {
  "node": "6.2.0"
}
62 trong mã của bạn. Ví dụ: để biết bạn đang chạy trên môi trường nào, hãy kiểm tra biến môi trường
"engines": {
  "node": "6.2.0"
}
63

$ mkdir my-new-project
$ cd my-new-project
$ npm init
5

Đây hiện là tên biến tiêu chuẩn được sử dụng trên hầu hết các nhà cung cấp dịch vụ lưu trữ đám mây

Nếu bạn cần tải thêm cấu hình, bạn có thể sử dụng một mô-đun như https. //github. com/indexzero/nconf

Một tùy chọn phổ biến khác để tải các biến môi trường là https. //github. com/motdotla/dotenv (Cảm ơn @szabi)

5. Sử dụng một hướng dẫn phong cách

Tôi biết tất cả chúng ta đều có những khoảnh khắc khi lần đầu tiên mở một tệp mới từ một dự án khác hoặc tệp đến từ một nhà phát triển khác, sau đó chúng tôi dành một giờ tiếp theo để định dạng lại các dấu ngoặc nằm trên các dòng khác nhau, thay đổi khoảng trắng thành . Vấn đề ở đây là sự kết hợp giữa các nhà phát triển cố chấp và không có hướng dẫn về phong cách tiêu chuẩn của nhóm/công ty

Mã trên cơ sở mã sẽ dễ hiểu hơn nhiều nếu tất cả được viết theo một phong cách nhất quán. Nó cũng làm giảm chi phí nhận thức về việc bạn nên viết bằng tab hay dấu cách. Nếu phong cách được ra lệnh (và được thực thi bằng cách sử dụng JSHint, ESlint hoặc JSCS) thì đột nhiên, cơ sở mã trở nên dễ quản lý hơn rất nhiều

Bạn cũng không cần phải đưa ra các quy tắc của riêng mình, đôi khi tốt hơn là chọn một bộ nguyên tắc hiện có và tuân theo chúng. Dưới đây là một số ví dụ tốt

  • Airbnb - https. //github. com/airbnb/javascript
  • Google-https. //Google. github. io/hướng dẫn phong cách/hướng dẫn javascript. xml
  • jquery-https. //Góp phần. jquery. org/style-guide/js/
  • JS tiêu chuẩn - http. //tiêu chuẩn. com/ - cảm ơn @szabi đã chỉ ra cái này

Chỉ cần chọn một và gắn bó với nó

6. Ôm không đồng bộ

Tôi chắc rằng bạn đã nghe tất cả những lời quảng cáo về những lời hứa, thậm chí có thể nghe một chút về async/await và trình tạo trong ES2016. Ý tưởng chính đằng sau tất cả các kỹ thuật này là làm cho mã của bạn không đồng bộ

Vấn đề với các hàm đồng bộ trong JavaScript là chúng chặn bất kỳ mã nào khác chạy cho đến khi chúng hoàn thành. Tuy nhiên, mã đồng bộ làm cho luồng logic ứng dụng của bạn trở nên dễ hiểu. Mặt khác, các cấu trúc không đồng bộ như lời hứa thực sự mang lại rất nhiều lý do đó trong khi vẫn giữ cho mã của bạn không bị tắc nghẽn

Vì vậy, trước tiên, tôi thực sự khuyên bạn nên chạy ứng dụng của mình (chỉ trong quá trình phát triển) với cờ

"engines": {
  "node": "6.2.0"
}
64. Thao tác này sẽ in cảnh báo và theo dõi ngăn xếp bất cứ khi nào ứng dụng của bạn sử dụng API đồng bộ

Có rất nhiều bài viết hay về cách sử dụng lời hứa, trình tạo và async/await. Tôi không cần sao chép tác phẩm tuyệt vời khác đã có sẵn, vì vậy đây là một vài liên kết để giúp bạn bắt đầu

  • Lời hứa - http. //www. html5rocks. com/en/tutorials/es6/promises/
  • Không đồng bộ / Đang chờ - https. //www. twilio. com/blog/2015/10/asyncawait-the-hero-javascript-deworthy. html
  • Trình tạo - https. // nhà phát triển. mozilla. org/vi/docs/Web/JavaScript/Hướng dẫn/Iterators_and_Generators

7. Xử lý lỗi

Gặp lỗi khiến toàn bộ ứng dụng của bạn ngừng hoạt động trong quá trình sản xuất không bao giờ là một trải nghiệm tuyệt vời. Quản lý ngoại lệ tốt rất quan trọng đối với bất kỳ ứng dụng nào và cách tốt nhất để xử lý lỗi là sử dụng các cấu trúc không đồng bộ ở trên. Ví dụ: các lời hứa cung cấp một trình xử lý

"engines": {
  "node": "6.2.0"
}
65 sẽ truyền bá tất cả các lỗi sẽ được xử lý sạch sẽ

Giả sử bạn có một chuỗi các lời hứa và bất kỳ lời hứa nào trong số đó có thể đột ngột thất bại, bạn có thể dễ dàng xử lý lỗi như sau

$ mkdir my-new-project
$ cd my-new-project
$ npm init
8

Trong ví dụ trên, không quan trọng chức năng nào trước đó có thể bị lỗi, bất kỳ lỗi nào cũng sẽ kết thúc trong tệp

"engines": {
  "node": "6.2.0"
}
66

8. Đảm bảo ứng dụng của bạn tự động khởi động lại

Được rồi, vậy là bạn đã làm theo cách tốt nhất để xử lý lỗi. Thật không may, một số lỗi từ một phần phụ thuộc vẫn bằng cách nào đó đã làm hỏng ứng dụng của bạn

Javascript là một thảm họa

Đây là lúc điều quan trọng là đảm bảo bạn sử dụng trình quản lý quy trình để đảm bảo ứng dụng phục hồi nhanh chóng sau lỗi thời gian chạy. Kịch bản khác mà bạn cần khởi động lại là nếu toàn bộ máy chủ bạn đang chạy bị hỏng. Trong tình huống đó, bạn muốn thời gian ngừng hoạt động ở mức tối thiểu và để ứng dụng của bạn khởi động lại ngay khi máy chủ hoạt động trở lại

Tôi khuyên bạn nên sử dụng PM2 http của KeyMetric. // chiều2. keymetrics. io/ để quản lý quy trình của bạn. Mặc dù các tùy chọn khác bao gồm (Nodemon)[http. //nodemon. io/] (cảm ơn @szabi) và (Mãi mãi)[https. //github. com/foreverjs/mãi mãi]

Javascript là một thảm họa

Đầu tiên, cài đặt nó như một mô-đun toàn cầu

"engines": {
  "node": "6.2.0"
}
0

Sau đó, để khởi chạy quy trình của bạn, bạn nên chạy

"engines": {
  "node": "6.2.0"
}
1

Để xử lý khởi động lại sau khi máy chủ gặp sự cố, bạn có thể làm theo hướng dẫn PM2 cho nền tảng của mình

  • http. // chiều2. keymetrics. io/docs/sử dụng/khởi động/

9. Nhóm ứng dụng của bạn để cải thiện hiệu suất và độ tin cậy

Theo mặc định Nút. js được chạy trong một tiến trình duy nhất. Lý tưởng nhất là bạn muốn có một quy trình cho mỗi lõi CPU để bạn có thể phân phối khối lượng công việc trên tất cả các lõi. Điều này cải thiện khả năng mở rộng của các ứng dụng web xử lý các yêu cầu HTTP và hiệu suất nói chung. Ngoài ra, nếu một công nhân gặp sự cố, những công nhân khác vẫn sẵn sàng xử lý các yêu cầu

Một trong những lợi ích khác của việc sử dụng trình quản lý quy trình như PM2 là nó hỗ trợ phân cụm ngay lập tức

  • http. // chiều2. keymetrics. io/docs/usage/cluster-mode/

Để khởi động nhiều phiên bản ứng dụng của bạn cho từng lõi trên máy, bạn chỉ cần chạy

"engines": {
  "node": "6.2.0"
}
2

Một điều cần lưu ý là mỗi quy trình đều độc lập — chúng không chia sẻ bộ nhớ hoặc tài nguyên. Ví dụ, mỗi quy trình sẽ mở các kết nối của riêng nó tới cơ sở dữ liệu. Luôn ghi nhớ điều đó khi bạn viết mã. Ví dụ, một công cụ hữu ích mà mọi người sử dụng để chia sẻ trạng thái phiên là Redis, công cụ này cung cấp kho dữ liệu trong bộ nhớ mà tất cả các quy trình có thể truy cập nhanh chóng để lưu trữ dữ liệu liên quan đến phiên

10. Yêu cầu tất cả các phụ thuộc của bạn lên phía trước

Tôi đã thấy nhiều nhà phát triển viết mã như thế này

"engines": {
  "node": "6.2.0"
}
0

Vấn đề với đoạn mã trên là khi ai đó đưa ra yêu cầu tới

"engines": {
  "node": "6.2.0"
}
67, lúc này mã sẽ tải tất cả các tệp theo yêu cầu của
"engines": {
  "node": "6.2.0"
}
68 — bất kỳ tệp nào trong số đó có thể tạo ra ngoại lệ. Ngoài ra, khi cấu hình được chuyển, cũng có thể xảy ra lỗi tại thời điểm đó có thể làm hỏng toàn bộ quá trình. Ngoài ra, chúng tôi không biết quá trình thiết lập đồng bộ tài nguyên sẽ mất bao lâu. Tại thời điểm này trong mã, về cơ bản, chúng tôi chặn tất cả các yêu cầu khác được xử lý

Vì vậy, bạn phải luôn tải trước tất cả các phụ thuộc của mình và định cấu hình chúng trước. Bằng cách đó, bạn sẽ biết ngay từ khi khởi động nếu có sự cố, không phải ba đến bốn giờ sau khi ứng dụng của bạn đi vào hoạt động trong sản xuất

11. Sử dụng thư viện ghi nhật ký để tăng khả năng hiển thị lỗi

"engines": {
  "node": "6.2.0"
}
69 là tuyệt vời nhưng nó có giới hạn trong một ứng dụng sản xuất. Cố gắng sàng lọc hàng ngàn dòng nhật ký để tìm ra nguyên nhân của lỗi… điều mà tôi đảm bảo rằng bạn sẽ phải làm vào một lúc nào đó, thật là khó khăn

Thư viện ghi nhật ký trưởng thành có thể trợ giúp việc này. Đầu tiên, chúng cho phép bạn thiết lập các mức cho mỗi thông điệp tường trình — cho dù đó là một

$ mkdir my-new-project
$ cd my-new-project
$ npm init
50,
$ mkdir my-new-project
$ cd my-new-project
$ npm init
51,
$ mkdir my-new-project
$ cd my-new-project
$ npm init
52 hay
$ mkdir my-new-project
$ cd my-new-project
$ npm init
53. Ngoài ra, chúng thường cho phép bạn đăng nhập vào các tệp khác nhau hoặc thậm chí kho dữ liệu từ xa

Ví dụ, trong các ứng dụng của tôi, tôi thường đăng nhập vào https. //www. loggly. com/. Loggly cho phép tôi nhanh chóng tìm kiếm tất cả các thông báo nhật ký của mình bằng các mẫu. Ngoài ra, nó có thể cảnh báo tôi nếu đạt đến ngưỡng — ví dụ: nếu ứng dụng web của tôi bắt đầu trả lại thông báo

$ mkdir my-new-project
$ cd my-new-project
$ npm init
54 cho người dùng của tôi trong khoảng thời gian dài hơn 30 giây, Loggly có thể gửi cho tôi một thông báo và tôi có thể biết chuyện gì đang xảy ra

Javascript là một thảm họa

Vậy bạn nên sử dụng thư viện nào? . Cá nhân tôi thích sử dụng

$ mkdir my-new-project
$ cd my-new-project
$ npm init
55 - https. //github. com/winstonjs/winston

12. Sử dụng $ mkdir my-new-project $ cd my-new-project $ npm init 56 nếu bạn đang viết một ứng dụng web

Nếu bạn đang viết một ứng dụng web, có rất nhiều phương pháp hay nhất phổ biến mà bạn nên tuân theo để bảo mật ứng dụng của mình

  • Bảo vệ XSS
  • Ngăn chặn Clickjacking bằng cách sử dụng
    $ mkdir my-new-project
    $ cd my-new-project
    $ npm init
    
    57
  • Bắt buộc tất cả các kết nối phải là HTTPS
  • Đặt tiêu đề
    $ mkdir my-new-project
    $ cd my-new-project
    $ npm init
    
    58
  • Vô hiệu hóa tiêu đề
    $ mkdir my-new-project
    $ cd my-new-project
    $ npm init
    
    59 để kẻ tấn công không thể thu hẹp các cuộc tấn công của chúng vào phần mềm cụ thể

Thay vì nhớ định cấu hình tất cả các tiêu đề này, Mũ bảo hiểm sẽ đặt tất cả chúng thành giá trị mặc định hợp lý cho bạn và cho phép bạn điều chỉnh những tiêu đề bạn cần

Javascript là một thảm họa

Nó cực kỳ đơn giản để thiết lập trên Express. ứng dụng js

"engines": {
  "node": "6.2.0"
}
1

Và sau đó trong mã của bạn khi thiết lập Express add

"engines": {
  "node": "6.2.0"
}
2

13. Giám sát các ứng dụng của bạn

Nhận thông báo khi có sự cố xảy ra với ứng dụng của bạn là rất quan trọng đối với các ứng dụng sản xuất. Bạn không muốn kiểm tra nguồn cấp dữ liệu Twitter của mình và thấy hàng nghìn người dùng tức giận nói với bạn rằng máy chủ của bạn bị hỏng hoặc ứng dụng của bạn bị hỏng trong vài giờ qua. Vì vậy, có thứ gì đó theo dõi và cảnh báo bạn về các vấn đề nghiêm trọng hoặc hành vi bất thường là rất quan trọng

Chúng tôi đã thảo luận về PM2 để quản lý quy trình. Ngoài ra, đó là nhà phát triển KeyMetrics. io chạy SaaS giám sát quy trình tích hợp với PM2 được tích hợp sẵn. Việc kích hoạt rất đơn giản và họ có gói miễn phí, đây là điểm khởi đầu tuyệt vời cho nhiều nhà phát triển. Khi bạn đã đăng ký Key Metrics, bạn chỉ cần chạy

"engines": {
  "node": "6.2.0"
}
3

Thao tác này sẽ bắt đầu gửi dữ liệu sử dụng bộ nhớ và CPU, cùng với báo cáo ngoại lệ đến các máy chủ chỉ số chính để xem từ trang tổng quan của họ. Bạn cũng có thể xem độ trễ của các yêu cầu http của mình hoặc thiết lập các sự kiện khi xảy ra sự cố (ví dụ: hết thời gian chờ đối với các phụ thuộc xuôi dòng)

Javascript là một thảm họa

Ngoài ra, Loggly (mà chúng tôi đã đề cập trước đó) cũng cung cấp giám sát dựa trên nhật ký. Cả hai công cụ kết hợp có thể cung cấp cho bạn cách phản ứng nhanh với các vấn đề trước khi chúng vượt quá tầm kiểm soát

14. Kiểm tra mã của bạn

Yeah, yeah, yeah - tôi biết tôi nên thử nghiệm. TDD và tất cả nhạc jazz đó

Nghiêm túc mà nói, thử nghiệm sẽ cứu nguy cho bạn trong nhiều trường hợp. Giống như việc tạo ra bất kỳ thói quen mới nào, thật khó để bắt đầu và duy trì động lực. Nó cản trở tốc độ phát triển của bạn. Tuy nhiên, tôi có thể nói từ kinh nghiệm rằng một khi một số vấn đề sản xuất đầu tiên xảy ra đối với một dự án không có thử nghiệm, bạn sẽ ước mình có ngay từ đầu

Bất kể bạn đang ở giai đoạn nào trong dự án, không bao giờ là quá muộn để giới thiệu thử nghiệm. Lời khuyên của tôi là bắt đầu nhỏ, bắt đầu đơn giản. Tôi cũng khuyên bạn nên viết bài kiểm tra cho mọi lỗi được báo cáo. Bằng cách đó bạn biết

  • Cách tạo lại lỗi (hãy đảm bảo rằng bài kiểm tra của bạn không thành công trước. )
  • Lỗi đó đã được khắc phục (đảm bảo bạn đã kiểm tra thành công sau khi khắc phục sự cố)
  • Lỗi đó sẽ không bao giờ xảy ra nữa (đảm bảo bạn chạy thử nghiệm trên mỗi lần triển khai mới)

Có rất nhiều thư viện thử nghiệm. Cá nhân tôi gắn bó với Jasmine vì tôi đã sử dụng nó trong một thời gian dài, nhưng

$ mkdir my-new-project
$ cd my-new-project
$ npm init
80,
$ mkdir my-new-project
$ cd my-new-project
$ npm init
81 hoặc bất kỳ thư viện nào khác cũng rất tuyệt. Nếu bạn cũng đang viết một ứng dụng web, tôi cũng khuyên bạn nên sử dụng Supertest để kiểm tra hộp đen các điểm cuối web của bạn

kết thúc

Và cùng với đó, thưa quý vị và các bạn, đó là những đề cử của tôi cho "14 phương pháp hay nhất" của Node. js

Nếu bạn muốn đề cử thêm một Node. js, vui lòng làm như vậy trong phần nhận xét. Hãy cứu thế giới của Node. dự án js cùng nhau.

Javascript là một thảm họa

Nút. jsBeginnerMẹo Các phương pháp hay nhất

Báo cáo

Thưởng thức bài viết này?

109

Javascript là một thảm họa
26

Đăng lại

Matt Goldspink

Kỹ sư trưởng với hơn 10 năm kinh nghiệm phát triển & nền tảng trong việc cung cấp các khóa đào tạo

Tôi đã cung cấp các khóa đào tạo kỹ thuật trong hơn 7 năm về nhiều chủ đề khác nhau - Tôi có thể trợ giúp bằng cách cung cấp các khóa học đầy đủ, lập trình cặp để giúp bạn học hoặc nếu bạn gặp vấn đề cụ thể mà bạn đang cố gắng giải quyết, tôi sẽ hỗ trợ

Theo dõi

Khám phá và đọc thêm các bài viết từ Matt Goldspink

bắt đầu

Thưởng thức bài viết này?

Để lại một lượt thích và bình luận cho Matt

109

Javascript là một thảm họa
26

Javascript là một thảm họa
Hãy là người đầu tiên chia sẻ ý kiến ​​của bạn

Javascript là một thảm họa
Hỗ trợ đánh dấu hương vị GitHub

Gửi đi

Shalom Halbert

3 năm trước

Là một Nhà phát triển Android đang cố gắng bắt đầu với Javascript, bài đăng này cực kỳ hữu ích. Cảm ơn bạn