关于javascript:JavaScript高级程序设计笔记03-语言基础

42次阅读

共计 9103 个字符,预计需要花费 23 分钟才能阅读完成。

语言根底

次要基于 ES6。

所有都辨别大小写。无论变量、函数名还是操作符

标识符

变量名、函数名、属性名、参数名

可由一个或多个字符组成:

  • 第一个必须是字母、_或者 $;
  • 其余的能够是字母、_、$ 或者数字。

其中字母能够是扩大 ASCII 中的字母,也能够是 Unicode 的字母字符,如À和Æ(但不举荐)

常规应用小驼峰模式(与内置函数和对象的命名形式统一)

严格模式

ES5 减少。

不平安的流动 抛出谬误

开启形式:"use strict";

预处理指令

保留字、关键字

关键字:有非凡用处,不能用作标识符或属性名

保留字:保留给未来做关键字用(不能做标识符,但还可做属性名,个别最好不必,思考兼容)

变量

  1. var 申明

    不初始化时默认值为 undefined。作用域:函数作用域

    • 变量晋升
    • 全局的申明会成为 window 对象的一个属性
    • 能够反复申明(在晋升顶部后合并为一个申明)
  2. let 申明

    作用域:块作用域

    • 暂时性死区(在 let 申明之前不能引用)
    • 在全局中申明的变量不会成为 window 对象的属性(仍会在页面的生命周期内存续)
    • 同一个块作用域不容许呈现冗余申明(JavaScript 引擎会 记录 用于变量申明的标识符及其所在的块作用域)。在申明之前无奈百分百确定之前没有申明过(假如没有申明过);无奈用 try/catch 来捕捉或者 if 语句来判断,因为会限制住 let 申明的作用域(不能进行条件申明)

    for 循环中的 let 申明:迭代变量的作用域仅限于 for 循环块外部。JavaScript 引擎会在后盾为每个迭代循环申明一个新的迭代变量

  3. const 申明

    行为与 let 基本相同,惟一区别在于申明变量时必须同时初始化且之后不能进行批改。

    仅限度它指向的变量的援用。若批改援用外部的属性,并不违反 const 的限度。

    能够让动态代码剖析工具提前发现不非法的赋值操作。

    for..of / for..in 循环:每次迭代只是创立一个新变量

少用 var,const 优先,let 次之

数据类型

6 种简略数据类型(原始类型):undefined、null、boolean、number、string、symbol。

1 种简单数据类型:object(无序键值对的汇合)

判断根本类型——typeof:一个操作符,非函数

  • “undefined”:值未定义、变量未声明
  • “boolean”
  • “string”
  • “number”
  • “object”:对象(非函数)或 null(被认为是一个对空对象的援用)
  • “function”:函数(在 ES 中被认为是对象,不代表一种数据类型,有本人的非凡属性)
  • “symbol”

1. Undefined 类型

个别不用于显式赋值,字面量 undefined 次要用于比拟。

倡议在申明变量的同时初始化,如果 typeof 失去 undefined 能够确定是因为变量未声明。

undefined 是一个假值,检测时要明确:检测 undefined 字面量还是假值。

变量未声明时惟一可执行的操作:typeof

2.Null 类型

示意一个空对象指针。只有一个值:null。

初始化一个未来要保留对象值得变量,倡议应用 null。能够放弃 null 是空对象指针的语义。

undefined 由 null 派生而来。因而 ECMA-262 将它们定义为外表上相等(== 等于操作符)。

null 是一个假值,检测时要明确:检测 null 字面量还是假值。

3.Boolean 类型

有两个字面量 true 和 false。

所有其余 ECMAScript 类型的值都有相应布尔值的等价模式。可应用 Boolean()转型函数,将其余类型的值转换为布尔值。

假值:

  • string:空字串
  • number:0、NaN
  • object:null
  • undefined
  • boolean:false

4.Number 类型

应用 IEEE 754 格局示意整数和浮点数(双精度数)。

不同的数值类型(不同进制)有不同的数值字面量格局。

前缀:八进制 0o,十六进制:0x

在所有 数学操作 中都被视为十进制数值

  • 浮点值

    必须蕴含小数点,且小数点后必须至多有一个数字。

    因为存储浮点值应用的内存空间是存储整数值的两倍,所以 ECMAScript 总千方百计把值转换为整数。1)小数点后没有数字;2)小数点前面跟着 0

    十分大或者十分小的数值,能够用迷信计数法来示意(格局:一个数值 +E/e+ 一个要乘的 10 的多少次冥)。默认状况下,ECMAScript 会将小数点后至多蕴含 6 个 0 的浮点值转换为迷信计数法。

    浮点值的精确度最高可达 17 位小数,但在算术计算中远不如整数准确。(如检测两数之和是否为 0.3)

  • 值的范畴

    因为内存的限度,不反对示意世上的所有数值。

    Number.MIN_VALUE——少数浏览器为 5e-324

    Number.MAX_VALUE——少数浏览器中为 1.797 693 134 862 315 7e+308

    超出可示意的范畴,会主动转换为一个非凡的无穷大值:Infinity(Numer.POSITIVE_INFINITY)和 -Infinity(Numer.NEGATIVE_INFINITY)。不能再进一步用于任何计算。isFinite()函数可用于检测判断是否超出范围。

  • NaN

    用于示意本要返回数值的操作失败了(而不是抛出谬误)

    • 任何波及 NaN 的操作始终返回 NaN
    • NaN 不等于包含 NaN 在内的任何值
    • isNaN()函数,会尝试把参数转换为数值
  • 数值转换

    3 个函数:Number()、parseInt()和 parseFloat()。

    Number()是转型函数,可用于任何数据类型;后两者次要用于将字符串转换为数值。

    字符串转型规定:

    1. 蕴含数值字符
    2. 蕴含无效的浮点值格局
    3. 蕴含无效的十六进制格局
    4. 空字符串——0
    5. 蕴含上述情况之外的其余字符——NaN

    对象转型规定:

    1. 调用 valueOf()办法
    2. 如果转换后果为 NaN,持续调用 toString()办法

    一元加操作符与 Number()函数遵循雷同的转换规则。

    转换字符串须要失去整数时,可优先应用 parseInt()函数:从第一个非空格字符开始转换。空字符串——>NaN。可选第二个参数,用于指定底数(进制数)。

    parseFloat()函数:1)结尾的零始终疏忽;2)只解析十进制值

5.String 类型

示意零或多个 16 位 Unicode 字符序列。

  • 一些字符字面量:用于示意非打印字符或有其余用处的字符

    \xnn,以 16 进制编码 nn 示意的字符,如 \x41 等于 ”A”。

    \unnnn,以 16 进制编码 nnnn 示意的 Unicode 字符,如 \u03a3 等于希腊字符”Σ“。

    能够作为单个字符被解释。

    .length 返回的是字符串中 16 位字符 的个数。(如果蕴含双字节字符,那可能返回的值不是精确的字符数)

  • 特点

    • 不可销毁:要批改某个变量中的字符串值,必先销毁原始的字符串,再将蕴含新值的另一个字符串保留到该变量。
  • 转换为字符串

    • toString()办法:数值、布尔值、对象和字符串值。null 和 undefined 没有。数值调用时能够接管一个参数指定底数。
    • String()转型函数

      可利用在 null 和 undefined(当不确定时)。

      如果值有 toString()办法,则调用该办法并返回。

      String(null); // "null"
      String(undefined); // "undefined"
      String(Object.create(null));
      // TypeError: Cannot convert object to primitive value

      用加号操作符一个值加上一个空字符串,也和 String()函数成果一样。

  • 模板字面量,应用反引号

    会保留反引号外部的空格、换行符。一种非凡的 JavaScript 句法表达式。

    个性:

    • 反对字符串插值:任何插入的变量从它们最靠近的作用域中取值(应用 toString()强制转型)。在定义时立刻求值并转换为字符串实例。
    • 反对定义标签函数(tag function):会接管被插值记号分隔的字符串数组和对每个插值表达式的求值后果。例子:

      let a = 6, b = 9;
      function simpleTag(strings, aValExp, bValExp, sumExp) {console.log( strings);
      }
      let untaggedResult = `${a} + ${b} = ${a + b}`;
      console.log(untaggedResult); // "6 + 9 = 15"
      let taggedResult = simpleTag`${a} + ${b} = ${a + b}`;
      // [""," + "," = ","", raw: Array(4)]

      因为表达式参数的数量是可变的,通常应用残余操作符(rest operator)将它们收集到一个数组中:

      function simpleTag(strings, ...expressions) {console.log( strings);
      }
      // 将 strings 和 expressions 的内容拼接起来可失去和 untaggedResult 一样的后果
    • 原始字符串

      String.raw // 标签函数
      // 可间接获取原始的模板字面量内容(如换行符或 Unicode 字符),而不是被转换后的字符.
      // 但对理论的换行符来说不行

      标签函数的第一个参数,即字符串数组,有 raw 属性,能够获得每个字符串的原始内容。

6.Symbol 类型

原始值。惟一的、不可变的。用处:确保对象属性应用惟一标识符,不会产生属性抵触的危险。

用来创立惟一记号,用作非字符串模式的对象属性。

没有字面量语法、不能用作构造函数(防止创立符号包装对象)

String(Symbol()); // "Symbol()"
Object(Symbol()); // Symbol {Symbol()}
Object(Symbol()).toString(); // "Symbol()"
  • 根本用法

    Symbol()Symbol('xx')。参数与符号定义或标识齐全无关,只是对符号的形容

  • 应用全局符号注册表

    用处:不同局部须要共享和重用符号实例。

    做法:用一个字符串作为键,在全局符号注册表中创立并重用符号。

    Symbol.for('xx');对每个字符串键都执行幂等操作。必须应用字符串键(被转换为字符串)来创立。

    Symbol.keyFor(s);返回该全局符号对应的字符串键。非全局符号返回 undefined;非符号抛出 TypeError。

  • 主要用途

    应用符号作为属性键

    Object.getOwnPropertySymbols();
    Object.getOwnProperyDescriptors();
    Reflect.ownKeys();

    如果没有显式保留对符号键的援用,那必须遍历对象的所有符号键能力找到相应的属性键。

  • 罕用内置符号:全局函数 Symbol 的一般字符串属性

    用于裸露语言外部行为,开发者能够间接拜访、重写或者模仿这些行为。。

    最重要用处之一:从新定义它们,从而扭转原生构造的行为。

    名称:在标准中的名称,前缀为 @@。如 @@iterator,即 Symbol.iterator

    • Symbol.asyncIterator ES9

      一个办法,返回对象默认的 AsyncIterator。示意实现异步迭代器 API 的函数

      函数生成的对象(迭代器?)应该通过其 next()办法陆续返回 Promise 实例

      for-await-of 中应用

    • Symbol.hasInstance

      一个办法,决定一个结构器对象是否认可一个对象是它的实例。定义在 Function 的原型上,默认在所有函数和类上都能够调用。能够在继承的类上通过静态方法从新定义这个函数。

      由 instanceof 操作符应用。

      ClassA[Symbol.hasInstance](obj);等价于obj instanceof ClassA

    • Symbol.isConcatSpreadable

      一个布尔值,为 true,则对象应该用 Array.prototype.concat()打平其数组元素。

      数组对象:默认会被打平到已有的数组,false 或假值会作为一个元素追加到数组开端

      类数组对象:默认作为一个元素追加到数组开端,true 或真值会把这个类数组对象被打平到数组实例

      其余非类数组对象:默认作为一个元素追加到数组开端,true 或真值下将被疏忽。

    • Symbol.iterator

      一个办法,返回对象默认的迭代器。示意实现迭代器 API 的函数

      for-of 中应用

    • 字符串匹配用到的符号

      1. Symbol.match(接管一个参数:字符串实例): 一个正则表达式办法,用正则表达式去匹配字符串。RegExp 的原型上默认有这个函数的定义。由 String.prototype.match() 办法应用:传入非正则值会被转换为 RegExp 对象。
      2. Symbol.replace(接管两个参数:字符串实例和替换字符串):一个正则表达式办法,替换一个字符串中匹配的子串。RegExp 的原型上默认有这个函数的定义。由 String.prototype.replace() 办法应用:传入非正则值会被转换为 RegExp 对象。
      3. Symbol.search(接管一个参数:字符串实例):一个正则表达式办法,返回字符串中匹配正则表达式的索引。RegExp 的原型上默认有这个函数的定义。由 String.prototype.search() 办法应用:传入非正则值会被转换为 RegExp 对象,默认等于.match 后果的 index 属性值(?)
      4. Symbol.split(接管一个参数:字符串实例):一个正则表达式办法,在匹配正则表达式的索引地位拆分字符串。RegExp 的原型上默认有这个函数的定义。由 String.prototype.split() 办法应用:传入非正则值会被转换为 RegExp 对象
    • Symbol.species

      一个函数值,该函数作为创立 派生对象 的构造函数。罕用于内置类型的派生类型中,能够笼罩新创建实例的原型定义。(用于实例办法的返回值裸露实例化派生对象的办法)

      class Baz extends Array {static get [Symbol.species] () {return Array;}
      }
    • Symbol.toPrimitive

      一个办法,将对象转换为相应的原始值。由 ToPrimitive 形象操作应用。

      依据提供给这个函数的参数(string、number 或 default),能够管制返回的原始值。

    • Symbol.toStringTag

      一个字符串,该字符串用于创建对象的默认字符串形容。由内置办法 Object.prototype.toString() 应用。相似[object XXX]

    • Symbol.unscopables

      一个对象,该对象所有的以及继承的属性,都会从关联对象的 with 环境绑定中排除。设置这个符号并让其映射对应属性的键值为 true,就能够组织该属性呈现在 with 环境中。

      let o = {foo: 'bar'};
      with(o) {console.log( foo); // bar
      }
      o[Symbol.unscopables] = {foo: true};
      with(o) {console.log( foo); // ReferenceError: foo is not defined
      }

7.Object 类型

一组数据和性能的汇合。

在 ECMAScript 中 Object 是派生其余对象的基类。

操作符

ECMA-262 形容了一组可用于操作数据值的操作符。

在利用给对象时,操作符通常会调用 valueOf()和 / 或 toString()办法来获得能够计算的值。

  • 一元操作符(unary operator):只操作一个值

    • 递增 / 递加操作符(前缀,先计算再给表达式求值;后缀,先给表达式求值再计算):其余类型值被转型为 Number 类型后再计算
    • 一元加

      在数值前头无影响,在非数值前头,会执行与 Number()转型函数一样的成果

    • 一元减

      在数值前头变成负值,在非数值前头,会执行与 Number()转型函数一样的成果,再取负值

  • 位操作符:用于数值的底层操作,也就是操作内存中示意数据的比特(位)

    位操作符不间接利用到 64 位示意,而是先把值转换为 32 位整数,再进行位操作,之后再把后果转换为 64 位。

    有符号整数(默认):第 32 位示意数值的符号(符号位,sign bit),它决定了数值其余部分的格局。正值以真正的二级制格局存储,负值以一种称为 二补数 的二级制编码存储(找到绝对值,按位非(一补数),再加一)。无法访问符号位。

    NaN 和 Infinity 在位操作中都会被当成 0 解决。

    利用到非数值时,会先通过 Number()函数转换为数值。

    • 按位非:用波浪号(~)示意,作用是返回数值的一补数。成果与对数值取反并减 1 一样。

      ~~n 等于 n 对于整数

      ~~n 等于 n 的整数局部,对于非整数的数值

    • 按位与:&。只在两位上都是 1 的时候返回 1。
    • 按位或:|。在两位上至多存在一位 1 就返回 1。
    • 按位异或:^。只在一位上是 1 的时候返回 1。失去的后果小于等于按位或的后果

      按位与 + 按位异或 = 按位或(?)

    • 左移:<<。右端以 0 填充,保留操作数值的符号。
    • 有符号右移:>>。左端以符号位的值来填充
    • 无符号右移:>>>。会给左侧空位补 0,符号位会跟着一起挪动。
  • 布尔操作符:非布尔类型,会先将操作数转换为布尔值

    • 逻辑非:!
    • 逻辑与:&&

      一种短路操作符。如果第一个操作数决定了后果(false),那么永远不会对第二个操作数求值。

    • 逻辑或:||

      也是一种短路操作符。如果第一个操作数为(true),第二个操作数就不会再被求值。能够用于防止给变量赋值 null 或 undefined(首选、备用)

  • 乘性操作符

    在解决非数值时,也会蕴含一些主动的类型转换

    • 乘法操作符:*

      有限 *0 => NaN

      有限 * 非 0 => Infinity/-Infinity

      任意 *NaN => NaN

    • 除法操作符:/

      任意操作数为 NaN => NaN

      0/0 => NaN

      有限 / 有限 => NaN

      非 0 /0 => Infinity/-Infinity

      有限 / 任意 => Infinity/-Infinity

    • 取模操作符:% 取余数

      有限 % 任意值 => NaN

      无限 % 有限 => 本身

      无限 %0 => NaN

  • 指数操作符:**。相当于 Math.pow()。

    也能够用 **=

  • 加性操作符

    • 加法

      1. 两个操作数都是数值
      2. 存在至多一个操作数是字符串(另一操作数转换为字符串),进行字符串拼接
    • 减法

      存在非数值,就转换为数值再进行计算

  • 关系操作符,包含小于、大于、小于等于和大于等于

    1. 都是数值,执行数值比拟
    2. 都是字符串,一一比拟字符串中对应字符的编码
    3. 任一操作数是数值,则将另一个转换为数值,在执行数值比拟
    4. 任一操作数是对象,调用 valueOf()依据后果进行比拟,没有 valueOf 就调用 toString()办法
    5. 任一操作数是布尔值,转换为数值再执行比拟
    6. 在波及比拟 NaN 时都返回 false
  • 相等操作符

    • 相等与不相等

      在比拟之前会执行类型转换。强制类型转换规定:

      1. 任一操作数是布尔值;则将其转为数值
      2. 一个字符串,一个数值;则尝试将字符串转为数值
      3. 存在一个对象,另一个不是;则调用对象的 valueOf()办法获得其原始值

      比拟规定:

      1. null 与 undefined 相等,两者都不能转换为其余类型的值再进行比拟
      2. 任一操作数为 NaN,相等操作返回 false,不相等操作返回 true
      3. 都是对象,指向同一个对象相等操作返回 true,否则返回 false。
    • 全等与不全等

      在比拟时不转换操作数。在不转换的前提下相等,全等操作才为 true。

      举荐应用全等和不全等,有助于在代码中放弃数据类型的完整性。

  • 条件操作符:三目运算(?:)
  • 赋值操作符:右值赋值给左变量。

    复合赋值(简写语法,不会晋升性能):

    *= | /= | %= | += | -= | <<= | >>= | >>>= |

  • 逗号操作符:最终返回表达式中最初一个值

    罕用场景:同时申明多个变量

语句

以分号结尾。可省略(由解释器本人确定语句在哪里结尾)。

增加分号的益处:

  1. 防止输出内容不残缺
  2. 便于通过删除空行来压缩代码
  3. 有助于在某些状况下晋升性能(缩小解释器的剖析工作)

应用代码块(左右花括号{})的益处:

  1. 让内容更清晰
  2. 批改代码时缩小出错的可能性

控制流语句:

  1. if 语句。主动调用 Boolean()函数将表达式转换为布尔值
  2. do-while 语句。一种后测试循环语句,循环体内的代码至多执行一次
  3. while 语句。一种先测试循环语句,循环体内的代码可能不会执行
  4. for 语句。也是先测试语句,减少了进入循环之前的初始化代码,以及每次循环执行后要执行的表达式。

    初始化、条件表达式和循环后表达式都不是必须的。能够创立一个无穷循环。

    如果只蕴含条件表达式,则实际上就变成了 while 循环

  5. for-in 语句。严格的迭代语句,用于枚举对象中的非符号键属性

    为了确保局部变量不被批改,举荐应用 const

    对象的属性是无序的,因而 for-in 语句不能保障返回对象属性的程序

  6. for-of 语句。严格的迭代语句,用于遍历可迭代对象的元素。

    依照可迭代对象的默认迭代器的 next()办法产生值得程序迭代元素;如果尝试迭代的变量不反对迭代,抛出谬误 TypeError

  7. 标签语句。用于给语句加标签

    典型利用场景:嵌套循环

    label: statement
    start: for(let i = 0; i < 5; i++) {}
  8. break 和 continue 语句

    break:退出循环

    continue:退出以后迭代,进行下一次迭代

    能够和标签语句一起应用,返回代码中特定的地位,通常是在嵌套循环中

  9. with 语句。将代码作用域设置为特定的对象。次要场景:针对一个对象重复操作

    with 代码块中,如何查找变量:1)找局部变量;2)没有找到,搜寻 with 绑定的对象,是否存在同名属性;3)没有找到,沿作用域链持续查找。

    严格模式不容许应用

  10. switch 语句。一种与 if 语句相干的控制流语句。

    为防止不必要的条件判断,最好给每个条件前面都加上 break 语句;如果的确须要间断匹配几个条件,举荐写个正文。

    ECMAScript 中的个性:

    • 能够用于所有数据类型(很多语言中只能用于数值),能够应用字符串甚至对象。
    • 条件的值(case 前面的值)不须要是常量,也能够是变量或表达式

      let num = 25;
      switch(true) {
        case num < 0:break;
        case num >= 0 && num <= 10: break;
        case num > 10 && num <= 20: break;
        default: ;
      }
      // 条件的表达式别离被求值,直到有表达式返回 true,否则就会始终跳到 default 语句
      // 在比拟每个条件的值时会应用全等操作符

函数

能够封装语句。

不须要指定是否返回值。除了 return 语句之外没有任何非凡申明表明该函数有返回值。return 语句也能够不带返回值,此时函数会立刻进行执行并返回 undefined;最罕用于提前终止函数执行。

最佳实际:要么返回值,要么不返回值。而不是只在某个条件下返回值。

正文完
 0