[关闭]
@smilence 2020-02-28T13:55:22.000000Z 字数 4274 阅读 920

Chapter 2: JavaScript as a Computer Language

JavaScript SDE-Foundations


1. Basics

1.1 Primitive Types

Boolean, Number, String, null, undefinedSymbol是primitive types,也就是基本类型。用===!==时,比较的是他们的value。注意,永远不要用==!=来比较变量。

JavaScript的Number不区分整数和小数,比如5/2的结果是2.5
String的literal可以用单引号或者双引号,但一般惯用单引号

变量没有被赋值时,JavaScript会认为它的值为undefined。当engineer想给variable赋一个代表空的值时,用null.

1.2 Variables

valid变量名必须以alphabet letter, _或者$开头。开头以外的字符可以用大多数字符,但不包括-

  1. // Variables can be declared without an initial value
  2. var foo;
  3. var bar = 42;

相比于var, const代表这个变量的value不会改变。如果这个变量初始值是个object,也就是说这个变量永远reference同一个object。

1.3 String

  1. var firstName = 'James';
  2. var lastName = 'Yu';
  3. // 用斜引号代表变量填空的string literal
  4. `My name is ${firstName} ${lastName}.` // "My name is James Yu"
  5. 'My name is ${firstName} ${lastName}.' // "My name is ${firstName} ${lastName}."

1.4 Function

1.4.1 function declaration

  1. function foo() {
  2. ...
  3. }

1.4.2 function expression

  1. var func = function() { // 这里就算给function起名也是无效的
  2. ...
  3. }
  4. func();

1.4.3 Arrow functions

通常都使用于一次性使用的情况,比如作为某个函数的参数,赋值给某个object的property等。 Brackets are optional when there's only one parameter / statement.

  1. (x, y) => { return x + y; }
  2. (x, y) => x + y
  3. //
  4. (x) => { return x * 2; } // no implicit return for JS
  5. x => x * 2
  6. () => { console.log('warning'); }

1.5 Control structures

1.5.1 if...else

  1. if (x > y) {
  2. max = x
  3. } else if (x < y) {
  4. max = y
  5. } else {
  6. max = x
  7. }

1.5.2 Loops

Generic, not specific to objects
  1. var number = 1
  2. var array = []
  3. while (array.length < 10) {
  4. array.push(number);
  5. number += 1;
  6. }
  7. var i = 0
  8. while (i < 10) {
  9. // do something about array[i]
  10. }
  11. // 类似ruby中的 range (0..n).each, 不局限于处理array
  12. for (var j = 0; j < 10; j++) {
  13. // do something about j
  14. }
  15. for (var j = 0; j < arr.length - 1; j++) {
  16. // do something about arr[j]
  17. }
Specific to objects
  1. // 访问obj的property name, 并不推荐用于array
  2. var april = {
  3. age: 18,
  4. name: 'April',
  5. };
  6. for (prop in april) {
  7. console.log(obj[prop]);
  8. }
Specifc to collections
  1. // 顺序访问array的property values
  2. var arr = [1,2,3,4,5,6,7,8,9,10];
  3. for (ele of array) {
  4. console.log(ele);
  5. }

2. Object

除了primitive types以外,其他的data都是object,所有的JavaScript function实际上也属于Function这个类别的object。而所有的object,都属于JavaScript当中的Object这个大类

Object可以被认为是一些property的组合,property可以解释为"a variable attached to the object", 除了附属于object以外,property与一般的变量没有什么不同,比如每个property都由property name和property value组成。property value可以是任意类型,自然也可以是Function object。

  1. e.g.
  2. function getAmountLimit(userId) {
  3. return location(userId) === 'US' ? 100 : 50
  4. }
  5. var obj = new Object();
  6. // 以下是一个object literal,也就是fixed value常量 ("literally"),类似于"abc"或者数字3.5
  7. var payment = {
  8. senderId: 100,
  9. receiverId: 101,
  10. amount: 30,
  11. amount_limit: getAmountLimit(senderId),
  12. }

2.1 Object comparison

对Object用===时,比较的是object的reference而不是object里的properties。(可以认为"objects are always represented as references", 所有object变量,存的都只是reference to the object)。所以一般不会用===去比较objects。

  1. [1,2] === [1,2] // false
  2. var user = {name: 'Tom'}
  3. var owner = user
  4. // user和owner reference的是同一个object,所以改了owner的name相当于改了user的name
  5. owner.name = 'James'
  6. user.name // 'James'

2.2 Properties

如果property name是valid变量名或者number,那么就可以省略引号。

  1. var obj = {
  2. foo: 0, // valid, could be variable name
  3. 'bar': 0, // string literals are always valid
  4. 123: 0, // number literals are always valid
  5. 1.5: 0, // ^
  6. foo-bar: 0, // invalid, would not be a valid variable name
  7. 'foo-bar': 0, // string literals are always valid
  8. };

通常情况下property可以用objectName.propertyName来访问。如果property name不是一个valid变量名,或者是动态的,比如来自于一个string变量,那么就必须用[]. 注意和ruby的hash一样,JavaScript不能从property value来得到property name.

  1. obj.0; // Error, not valid variable name
  2. var field = 'test';
  3. obj.field // Error, field is a variable, not a literal
  4. obj[field];
  5. obj['example' + i]; // Dynamic, equivalent to a variable
  6. obj.prop = value;
  7. obj['prop'] = value;
  8. delete obj.prop // 删除某个property
  1. // Nested property accessor,相比 [] 更清楚
  2. var obj = {foo: {bar: [42, 21]}};
  3. console.log(obj.foo.bar[0]);

3. Collections

3.1 Methods

  1. arr.includes(ele) // ruby: arr.include?(ele)
  2. arr.slice(1,5) // ruby: arr[1...5]
  3. arr.join(' ') // ruby: arr.join(" ")
  4. arr.shift() // ruby: arr.shift()
  5. arr.unshift() // ruby: arr.unshift()
  6. arr.pop() // ruby: arr.pop()
  7. arr.push() // ruby: arr.push()

3.2 Iteration methods

arr.forEach take function作为参数,但不使用function的结果。就像在ruby中arr.each会take block作为参数,但并不使用block的结果。

  1. arr.forEach(function(ele, idx) {
  2. arr[idx] = ele * 2; // 返回值不会被使用,所以也不需要返回值
  3. });
  4. const copy = []; // copy永远reference这个array,但array的内容可以变化
  5. arr.forEach((ele) => {
  6. copy.push(ele);
  7. });
  8. arr.forEach(ele => {
  9. copy.push(ele);
  10. });

其他Iteration method和Ruby中的对应函数相似,会使用function的结果

  1. const new_arr = arr.map(x => x*2); // ruby arr.map { |ele| ele*2 }
  2. const sum = arr.reduce((acc,ele) => acc + ele); // ruby arr.inject {|acc, ele| acc + ele}
  3. const sum = arr.reduce((acc,ele) => acc + ele, 0); // ruby arr.inject(0) {|acc, ele| acc + ele}
  4. const is_all_positive = arr.every(ele => ele > 0); // ruby arr.all? {|ele| ele > 0}
  5. const has_zero = arr.some(ele => ele === 0); // ruby arr.any? {|ele| ele == 0}

4. Prototypes

5. Scope*

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注