第3章:语言基础 [一起学前端](上篇)

52 阅读10分钟

第3章:语言基础 [一起学前端]

作者是位前端切图仔,本系列旨在从头开始学习前端,巩固前端基础。同时分享学习笔记供广大同学讨论,如有编写错误或者描述问题,还请大家多多指点。


3.1 语法

3.1.1 区分大小写

首先要知道的是,ECMAScript中一切都区分大小写。无论是变量、函数名还是操作符,都区分大小写。换句话说,变量test和变量Test是两个不同的变量。类似地,typeof不能作为函数名,因为它是一个关键字(可以认为是系统不给使用的名字)。但Typeof是一个完全有效的函数名。

3.1.2 标识符

所谓标识符,就是变量、函数、属性或函数参数的名称。标识符可以由一或多个下列字符组成:

  • 第一个字符必须是一个字母、下划线(_)或美元符号($)

  • 剩下的其他字符可以是字母、下划线、美元符号

按照滚利,ECMAScript标识符使用驼峰大小写形式,即第一个单词的首字母小写,后面每个单词的首字母大写这个和大部分公司的规范基本上是一致的。

3.1.3 注释

ECMAScript采用C语言风格的注释,包括单行注释和块注释。单行注释以两个斜杠字符开头

// 单行注释
/*
 这是多行注释
*/

3.1.4 严格模式

ECMAScript5增加了严格模式(strict mode)的概念。严格模式是一种不同的JavaScript解析和执行模型,ECMAScript3的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误。要对整个脚本启用严格模式,在脚本开头加上这一行

"use strict";

严格模式会进行很多的校验,比如变量 必须先声明后使用,不能使用with变量等等

3.1.5 语句

ECMAScrip中的语句以分号结尾。多条语句可以合并到一个C语言风格的代码块中。代码块由一个左花括号标识开始,一个右花括号标识结尾。

现在项目中基本都使用webpack打包工具,规范中不一定要求分号结尾,这个看不同公司的规范而定

在单行语句的时候可以省略花括号,但是实际编码的时候不建议省略,一个是不好阅读,二是后期扩展不好扩展

if(test)
    console.log(test) // 这样使用并不会有问题,但是不建议这样编写

if(test){
    console.log(test) // 这种写法就很好,语义明确,也方便后期扩展else
}

3.2 关键字与保留字

ECMA-262描述了一组保留的关键字,这些关键字有特殊用途,比如表示控制语句的开始和结束,或者执行特定的操作。按照规定,保留的关键字不能用作标识符或属性名。ECMA-262第6版规定的所有关键字如下:

break      do       in          typeof
case       else     instanceof  var
catch      export   new         void
class      extends  return      while
const      finally  super       with
continue   for      switch      yield
debugger   function this
default    if       throw
delete     import   try

规范中也描述了一组未来的保留字,同样不能用作标识符或属性名。虽然保留字在语言中没有特定用途,但他们是保留给将来做关键字用的。

始终保留
enum

严格模式下保留
implements    package     public
interface     protected   static
let           private

模块代码中保留
await 

3.3 变量

ES变量是松散类型的,意思是变量可以用于保存任何类型的数据。每个变量只不过是一个用于保存任意值的命名占位符。有3个关键字可以声明变量:varconstlet。其中var在ES的所有版本中都可以使用,而constlet只能在ES6及更晚的版本中使用。

3.3.1 var关键字

  • var 的声明会存在作用域,比如函数内部声明的变量,在外部无法访问

  • 不使用var 声明的变量,会提升到全局作用域,不建议这样使用,会导致代码难以阅读,另外在严格模式下会报错

  • var 声明的变量可以先使用,后声明,这个叫做变量提升

  • 可以使用var 对变量重复进行声明,并不会报错,但没有意义

  • var 声明的变量可以赋值任意类型,并不会报错,但实际开发中并不建议这样使用

function fn(){
    var a1=2323;
}
console.log(a1); // 会报错,产生了局部作用域,外面是无法访问的
function fn(){
  a2=2222;
}
console.log(a2); // 这里不会报错,因为a2被提升到了全局作用域,这样会污染全局变量,不建议这样使用
{
  console.log(a3);
  var a3=2222; // 这里可以先使用a3,下面再进行声明,不过可惜 上面的打印会输出 undefined,因为变量提升只能提前声明,并不能把赋值也提前
}
{
  var a=2323
  var a='23223'
  var a=false // 这些代码也不会报错,但是实际开发中不建议这样编写,会产生阅读障碍,另外变量的类型应该是确定的值,不能一会数字一会字符串,在类型判断的时候会出问题,比如现在开发都用TS了,要更加规避这个问题
}

3.3.2 let 声明

let 和 var 的作用差不多,都是用来声明变量,但是有着非常重要的区别。

  • let 是块级作用域,只要有块就是作用域,比如大括号,for 循环,if语句都是块作用域
  • let 变量不能重复声明
  • let 声明的变量不能变量提升,会产生暂时性死区,不能使用不能赋值
  • let 声明的变量不会挂载到window上,哪怕是在全局环境下声明。这个验证很简单,打开控制台试一试就知道了。
// 下面是一段神奇的示例代码
if(typeof name ==='undefined'){
  let name
}
name = 'math'
// 这个代码解读下来,1、判断全局下面有没有 name 这个变量;2、然后声明局部变量 name;3、给全局name进行赋值
// 所以并不能达到想要的效果

另外 try catch 的每个大括号都是一个作用域,并不互通

3.3.3 const声明

const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改const声明的变量会导致运行时错误。如果使用Babel转换为ES5的话,会变成var

const声明的限制只适用于它指向的变量的引用。换句话说,如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制。这里只要了解对象保存的是指针,并不是实际的值就能明白了

3.3.4 声明风格及最佳实践

ES6增加letconst从客观上为这门语言更精确地声明作用域和语义提供了更好的支持。行为怪异的var所造成的各种问题,已经让JavaScript社区为之苦恼了很多年。随着这两个新关键字的出现,新的有助于提升代码质量的最佳实践也逐渐显现。

  • 不使用var。有了let和const,大多数开发着会发现自己不再需要var了,限制自己只使用let和const有助于提升代码质量,因为变量有了明确的作用域、声明位置,以及不变的值。
  • const 优先,let次之。使用const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作。因此,很多开发者认为应该优先使用const来声明变量,只有提前知道未来会有修改时,再使用let。这样可以让开发者更有信心地推断某些变量的值永远不会变,同时也能迅速发展因意外赋值导致的非预期行为。

3.4 数据类型

ECMAScript 有 6 种简单数据类型(也称为原始类型):undefined、null、boolean、number、String和symbol。symbol(符号)是ES6新增的。还有一种复杂数据类型叫object(对象)。object是一种无序名值对的集合。因为再ECMAScript种不能定义自己的数据类型,所有值都可以用上述7种数据类型之一来表示。只有7种数据类型似乎不足以表示全部数据。但ECMAScript的数据类型很灵活,一种数据类型可以当作多种数据类型来使用。

3.4.1 typeof 操作符

对一个值使用typeof操作符会返回下列字符串之一:

  • undefined 表示值未定义
  • boolean 表示值为布尔值
  • string 表示值为字符串
  • number 表示值为数值
  • object 表示值为对象 或 null 这里也是面试题常考的问题之一
  • function 表示值为函数
  • symbol 表示值为符号

注意:调用typeof null 返回的是 “object”。书上说这是因为特殊值null 被认为是一个对空对象的引用

网上资料阐述 因为对象的前两位是0 null 的前两位也是0 故判断是一样的

注意 严格来说 函数在ES中被认为是对象,并不代表一种数据类型。可是,函数也有自己特殊的属性。为此,就有必要通过 typeof操作符来区分函数和其他对象

3.4.2 Undefined 类型

undefined 类型只有一个值,就是特殊值 undefined。当使用var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值

注意 一般来说,永远不用显式地给某个变量设置undefined值。字面值undefined主要用于比较,而且在ES3之前是不存在的。增加这个特殊值的目的就是为了正式明确对象指针(null)和未初始化变量的区别。

未声明的变量 使用 typeof 判断的时候,也是返回undefined

typeof abvcddsd
输出 :'undefined'
let a
typeof a
输出 :'undefined'

所以变量未声明 和 声明未初始化 返回的结果都是 undefined。所以在开发中在声明变量的时候,赋值初始值,避免判断失误

3.4.3 Null 类型

null 类型同样只有一个值,即特殊值 null。逻辑上讲,null值表示一个空对象指针,这也是给typeof 传一个null会返回object的原因。

任何时候,只要变量要保存对象,而当时又没有那个对象可保存,就要用null来填充该变量。这样就可以保持null是空对象指针的语义,并进一步将其与undefined区分开来

3.4.4 Boolean 类型

Boolean(布尔值)类型是ES中使用最频繁的类型之一,有两个字面值:true 和 false。这两个布尔值不同于数值,因此true 不等于1,false 不等于0

数据类型转换为true的值转换为false的值
String非空字符串空字符串 “”
Number非零数值(包括无穷值)0,NaN
Object任意对象null

了解上面的转换规制,方便在实际开发中进行逻辑判断

3.4.5 Number 类型

这个章节较多,等下次更新