JavaScript 是一种动态的、基于原型的语言。它有一些原始类型,除此之外的一切都被视为对象。
虽然它最为人熟知的身份是网页的脚本语言,但许多非浏览器环境也在使用它,比如 Node.js。这门语言一直在积极开发中;得益于它的多范式特性,它支持多种编程风格。JavaScript 是一门动态语言,支持面向对象、命令式和声明式(例如函数式编程)等风格。
在 JavaScript 中,给名称赋值主要有几种方式:使用变量或常量。在 Exercism 上,变量一律用 camelCase 书写,常量则用 SCREAMING_SNAKE_CASE 书写。并没有官方指南可循,不同的公司和组织也有各自的风格指南。你可以按自己喜欢的任何方式书写变量。按练习中准备好的方式书写,好处是它们在网页界面和大多数 IDE 中会有不同的高亮显示。
JavaScript 中的变量可以用const、let或var关键字来定义。
使用let或var时,一个变量在其生命周期内可以引用不同的值。例如,myFirstVariable可以用赋值运算符=定义和重新定义很多次:
let myFirstVariable = 1;
myFirstVariable = 'Some string';
myFirstVariable = new SomeComplexClass();
与let和var不同,用const定义的变量只能赋值一次。这正是 JavaScript 中定义常量的方式。
const MY_FIRST_CONSTANT = 10;
// Can not be re-assigned.
MY_FIRST_CONSTANT = 20;
// => TypeError: Assignment to constant variable.
const关键字在变量和常量中_都_会被提到。围绕常量经常提到的另一个概念是(不)可变性。
const关键字只让_绑定_不可变,也就是说,你只能给一个const变量赋值一次。在 JavaScript 中,只有原始值是不可变的。不过,非原始值仍然可以被修改。
const MY_MUTABLE_VALUE_CONSTANT = { food: 'apple' };
// This is possible
MY_MUTABLE_VALUE_CONSTANT.food = 'pear';
MY_MUTABLE_VALUE_CONSTANT;
// => { food: "pear" }
按照惯例,在 Exercism 以及许多其他组织和项目的风格指南中,不要修改看起来像const SCREAMING_SNAKE_CASE的值。从技术上说,这些值_可以_被修改,但为了清晰,也为了在 Exercism 上做好预期管理,我们不鼓励这样做。当_必须_强制这一点时,使用Object.freeze(value)。
const MY_VALUE_CONSTANT = Object.freeze({ food: 'apple' });
// This silently fails
MY_VALUE_CONSTANT.food = 'pear';
MY_VALUE_CONSTANT;
// => { food: "apple" }
在实际项目中,不太可能整个代码库里到处都看到Object.freeze,但永远不修改SCREAMING_SNAKE_CASE值是个好规则;它通常由 linter 之类的自动化分析工具来强制执行。
在 JavaScript 中,功能单元被封装在_函数_里,如果几个函数属于同一类东西,通常会把它们放在同一个文件中。这些函数可以接收形参(实参),并可以用return关键字_返回_一个值。函数通过()语法调用。
function add(num1, num2) {
return num1 + num2;
}
add(1, 3);
// => 4
💡 在 JavaScript 中,声明函数有_很多_不同的方式。这些方式看起来与使用
function关键字不同。该 track 会尝试逐步介绍它们,但如果你已经了解,可以随意使用任何一种。大多数情况下,用其中哪一种都谈不上更好或更差。
export和import关键字是把普通 JavaScript 文件变成JavaScript 模块的强大工具。除了让代码可以选择性地暴露组件(例如函数、类、变量和常量)之外,它还带来了一整套其他特性,比如:
一个具体的例子是 Exercism 的 JavaScript track 上测试的工作方式。每个练习至少有一个实现文件,例如lasagna.js,也至少有一个测试文件,例如lasagna.spec.js。实现文件用export暴露公开的 API,测试文件用import访问它们,测试就是这样检验实现的结果的。
// file.js
export const MY_VALUE = 10;
export function add(num1, num2) {
return num1 + num2;
}
// file.spec.js
import { MY_VALUE, add } from './file';
add(MY_VALUE, 5);
// => 15