二 基本语法

教程

https://wangdoc.com/javascript/basic/grammar.html

笔记

1. 语句和表达式的区别

语句主要是为了进行某种操作,一般情况下不需要返回值;表达式是为了得到返回值,一定会有一个返回值。

2. 声明变量未赋值

如果只是声明变量而没有复制,则该变量的值是 "undefined"。undefined 是一个 JavaScript 的关键字,表示 “无定义”。

3. 变量提升、函数提升及 ES6

3.1 变量提升的原理

JS 引擎工作的原理是,先解析代码,获取所有被声明的变量(也就是把文件中所有声明的变量都找出来,然后缓存到内存。这些变量只是声明了但未赋值,变量值自然是 undefined),然后再一行行地运行。这造成的结果就是,所有的变量声明语句,都会被提升到代码的头部,这就是变量提升。

3.2 变量提升的定义

教程:http://www.cnblogs.com/snandy/p/4552078.html
变量提升一个比较严谨的定义:在指定作用域里,从代码顺序上看是变量先使用后声明,但运行时变量的 “可访问性”提升到了当前作用域的顶部,其值为 undefined, 没有“可用性”。

  • 可访问性:访问该变量不会抛异常。
  • 可使用性:调用该变量进行运行,由于其值为 undefined,达不到原来的效果。
console.log(a);
var a = 1;

按照其他语言的经验,第一句应该报错。但是只是输出了 undefined。但是由于 js 是先解释再执行,实际上相当于执行了下面的代码:

// 无论在文件中哪里被声明的变量都被提升到头部了。
var a;
console.log(a);
a = 1;

3.2 函数表达式也会存在变量提升

function test(){
  alert(func);
  var func = function(){};
}
test();

这个程序会显示 alert : undefined。注意这个变量提升主要是用 var 声明变量的缘故。因为 var 声明的变量在 JS 解释阶段都会提升到当前作用域的顶部,所以值是 undefined。所以下面的例子会报错:

function test(){
  alert(func); // undefined.
  func(); // 抛出异常
 var func = func(){};
}

3.3 函数声明的名也会提升到当前作用域顶部

function test(){
  console.log(f1); // 会输出整个函数的定义。
  f1(); // called 
  function f1(){
    console.log("called");
  }
}

3.3 函数声明的名 与 3.2 函数表达式 是不一样的。
函数声明的变量名,是用 function 定义了一个函数,3.2 中的函数表达式是 var 修饰的一个变量。

用 function 定义的函数是更牛的,只要定义了,无论是在定义前使用还是在定义后使用都是 OK 的。这个特性也跟 JS 的解释器会先编译后运行有关。比如 Python 中就不能这么搞:

def a():
    print(b)
    b()
    def b():
        print("bb")

抛出的 error:

UnboundLocalError: local variable 'b' referenced before assignment

静态语言也不能这么搞,比如 go:

func test(){
    a()
    func a(){
        fmt.Println("gggg")
    }
}

我的 ide 直接飘红了。
可见 无论是函数名还是变量的提升,都是拙劣的设计,在写的时候需要避免。

3.4 ES6 中 let / const 的意义

使用 let / const 代替 var 后,变量提升的现象就不存在了。

function test() {
    alert(declaredButNotAssigned1); // 报异常
    alert(declaredButNotAssigned2); // 报异常
    alert(func); // 报异常
  
    let declaredButNotAssigned1;
    let declaredButNotAssigned2 = true;
    let func = function() {};
}
test();

4 标识符

  1. 允许使用 和 _, 在 Python 中是不允许使用 的。

5 注释

由于历史上 JavaScript 可以兼容 HTML 的注释,所以 也被视为合法的单行注释。但是需要注意, --> 只有放在行首才会被当成单行注释,否则会当做正常的运算。

// 自减运算符
a-- 

5 区块

用花括号括起来的语句叫做一个“区块”。
花括号限制不住 var 定义的变量,花括号外面 var 定义的变量依然有效。

{
  var a = 1;
}
a // 1 

但是 es6 的 let,花括号就能管住它。

{
  let a = 2;
}
a // Uncaught ReferenceError: c is not defined

6 条件语句

6.1 switch 结构

  • switch 结构与 Java 相同,需要加 break. Go 则不需要加 break。
  • Java 中的 Condition 必须是 byte / short / int 或 char / String 。JS 和 Go 则没有此限制。
  • Java 中 Case 的值的数据类型必须与 switch 中变量的类型相同。Go 中则要求 case 的数据类型保持一致即可。
switch(condition){
  case val:
  ...
  break;
  default:
  ...
}

6.2 三元运算符

// js & java
condition ? a : b
// python
a if condition else b 
// go 没有三元运算符 

7 条件语句

7.1 do... while 循环

这也是 JS 抄 Java 的地方,无论 while条件是否成立,do 至少执行一次。

do{
 语句 
} while(条件);

我觉得这个do...while 非常别扭,python 中也有类似较劲的 ---------- for ... else ...
for ... else ... 的用法是,如果 for 正常执行完成,则执行一次 else。
我一直觉得这个没什么卵用,但是在 A 公司,他们却这么干

for i in range(n):
  // 重试某个事情,比如重连操作
  if success:
    break
else:
  raise Exeception("重试失败")

7.2 break 和 continue 语句
这两个语句,之前也是知道用法,但是不知道使用场景。
重点在于这两句:

  • break 能中断一个循环,所以当一般和 if 配合使用,达到目的就中断。
  • continue 之后的代码在此次循环中不执行会被跳过,执行下一次代码。
    7.3 标签
label:
  语句

标签用的也比较少,使用场景是配合 continue 和 break, 跳出多重循环。

top:
  for(let i = 0;i<5;i++){
    for(let b=0;b<10;i++){
      if (b * i > 30){
          break top;
        }
  }
}

这样就把最外层的 for 循环给打断了,这样不就节省 CPU 了吗?
continue 的作用也是如此。

你可能感兴趣的:(二 基本语法)