跳转至

JavaScript 基础

注释

  • 单行注释 //
  • 多行注释 /* */

变量

变量声明

对值的具名引用。没有赋值的变量的值是undefined

使用var来声明变量;不使用var的声明可被执行。

var a = 1 + 3;
  • 变量具有动态类型。
  • 变量提升 所有使用var声明变量的语句都会被提升到代码的头部,并先执行。

在区块中的变量

对于var声明的变量来说,区块(Block)不构成单独的作用域(Scope)。

{
  var a = 1;
}
a;  // 1

命名规范

  1. 第一个字符可以是任意Unicode字母,以及美元符号$和下划线_
  2. 第二个字符以及其后字符还可以是数字。

数据类型

JavaScript中定义了7种数据类型:

  • number 数值
  • string 字符串
  • boolean 布尔值
  • undefined 未定义
  • null 空值
  • object 对象,包括狭义的对象object,数组array以及函数function
  • symbol 符号,ES6新增类型

typeof

可以使用typeof运算符来判断一个变量的类型,返回“number”等字符串。

因此可以用typeof来检查一个没有声明的变量而不报错。

由于历史原因,typeof null返回“object”。

nullundefined

if语句中两者都会自动被转换成false,使用==会报告两者相等。

Dart语言中只有null,没有undefined

null表示空对象,转换成数值时表示0;undefined表示未定义,转换成数值时表示NaN

调用函数时,未提供参数时,该参数返回undefined;函数无返回值时返回undefined

布尔值

以下值被自动转换为false

  1. undefined和null
  2. false
  3. 0
  4. NaN
  5. 空字符串 ''

使用Boolean()进行强制类型转换

数值

在Javascript内部,所有数值(包括整数)使用64位浮点数储存

由于64位浮点数的特性,绝对值小于2的53次方的整数都能精确地表示,即对15位的进制数都能精确处理

数值范围是[0, Infinity);Number对象提供MaxValueMinValue方法。

表示数值的字面值

  • 十进制:没有前导0的数值。
  • 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
  • 十六进制:有前缀0x或0X的数值。
  • 二进制:有前缀0b或0B的数值。

正零与负零

toString()方法都返回0

唯一有区别的场合是作为分母时分别得到+Infinity-Infinity

NaN

NaN参与的运算结果都是NaN

NaN是唯一的不等于自身的值,(NaN == NaN) === false, (NaN === NaN) === false

与数值相关的全局方法

  1. parseInt() 用于将字符串转换成整数 自动去除空格,返回NaN或转换后的数值 注意到 对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致**一些奇怪的结果**。

    parseInt(1000000000000000000000.5) // 1
    // 等同于
    parseInt('1e+21') // 1
    
    parseInt(0.0000008) // 8
    // 等同于
    parseInt('8e-7') // 8
    

    还可以附带第二个参数进行进制转换,parseInt('1010', 2); 2. parseFloat() 3. isNaN(), isFinite()

使用Number()进行强制类型转换

字符串

使用单引号或双引号均可,一般约定使用单引号,以与html相区分。

反斜线转义

  1. \HHH 八进制转义
  2. \xHH 十六进制转义
  3. \uXXXX Unicode转义

可以使用方括号语法访问字符串中的单个字符,但*无法改变*单个字符。

字符串具有length属性

使用String()进行强制类型转换

Base64

btoa(), atob()

对象

无序的键值对的集合

{
  foo: 'hello',
  bar: 'world'
};

键名又称属性。最后一个属性后面可以添加逗号

所有的键名都是字符串,因此加引号与否无影响。(数值键名会被自动转换为字符串,如果键名不满足作为标识符的条件,则必须加上引号)

var obj = {
  1p : 'Page 1',    // 报错
  h + w: 'H and W'  // 报错
};

var obj = {
  '1p': 'Page 1',
  'h + w': 'H and W'
}

键值可以是任何数据类型,包括函数。

属性的读取与赋值

点运算符或方括号运算符均可。

方括号运算符接受;数值键名不接受点运算符。

查看所有属性,可以使用Object.keys()

使用delete删除属性,成功后返回truedelete不能删除继承的属性。

判断属性是否存在,使用in运算符。

遍历可遍历的属性(包括继承的属性),使用for ... in循环。

for (var key in obj) {
  console.log(key);
  console.log(obj[key]);
}

with

建议不使用with语句。

作用是操纵同一对象的属性时提供书写的方便。

对象or表达式

{ foo: 123 }

为了消歧义,如果行首是括号,解释为对象;否则为语句块。

  1. 对象 ({ foo: 123 }) // 123
  2. 语句块 { foo: 123 } // {foo: 123}

函数

声明函数由三种方式

  1. function命令声明
  2. 函数表达式形式的声明
  3. 使用Function构造函数

函数表达式形式的声明,若有var f = function k() {...},则名称k只在函数内部有效。

函数若重复声明,后一次将覆盖前一次的声明,且由于变量提升和函数声明提升,前一次声明任何时候都是无效的。

函数的属性和方法

  • name属性 返回函数的名字;若函数为表达式形式,且为匿名函数,则返回变量的名字;若为具名函数,则返回此function关键字之后的函数名
  • length属性 返回函数定义时的参数个数
  • toString()方法 返回函数的源代码,包括其中的注释

作用域

函数执行时的作用域,是定义时的作用域而不是调用时所在的作用域。函数体内部声明的函数,作用域绑定函数体内部。

参数

Js允许省略参数而不报错,可以为参数传入undefined;支持默认参数。

参数的传递方式如下:

  1. 原始数据类型(数值、字符串、布尔值)按值传递 pass by value
  2. 对象按址传递 pass by reference

如果出现同名参数,则按名存取时取后一个参数名;访问前一个可以使用arguments关键字。

不定参数,可以通过arguments变量来获取,也可以使用三句点语法。

function add(...x) {
    return x.reduce((m, n) => m + n);
}

支持拓展参数,即通过...操作符将数组作为函数的参数使用而不需要使用apply()

arguments对象

arguments对象不是一个数组,但可以通过数值下标访问和具有length属性;严格模式下对arguments的修改是无效的。

闭包

“定义在函数内部的函数”,可以“记住诞生的环境”。

闭包的两大用处是:

  1. 可以读取函数内部声明的变量
  2. 可以使闭包诞生的环境持续存在
function createIncrementor(start) {
  return function () {
    return start++;
  };
}

var inc = createIncrementor(5);

inc() // 5
inc() // 6
inc() // 7

立即调用的函数表达式 IIFE

推而广之,任何让解释器以表达式来处理函数定义的方法,都能产生同样的效果,比如:

  1. (function () { /* code */ })();
  2. +function() { /* code */ }();

eval 对表达式求值

接受字符串作为参数,并将此字符串作为函数执行。

严格模式中,eval中声明的变量,不会影响到全局作用域,但仍可以读写当前作用域内的变量。

eval使用别名调用时,其作用域为全局作用域。

数组

按次序排列的一组值,数组是特殊的对象,其键名是依序排列的一组值。

Js数组使用32位整数保存数组长度length,最大长度为4294967295。length属性是可写的,总是比最大的数字键值多一,修改length时,数组会根据值删除已有元素或增加空位。读取空位时返回undefined

可以使用in运算符来检查数组的键,如果数组中的某位置是空位,in返回false

空位与undefined是不一样的,遍历数组时,空位会被跳过而undefined则不会。

类似数组的对象

具有length属性的对象是类似数组的对象,如函数的arguments

可以使用Array.prototype.slice.call()方法将类似数组的对象转换为数组。

数据类型的转换

强制类型转换

Number()

对于原始类型的值规则如下:

  1. 数值转换后为原来的值。
  2. 可以解析为数值的字符串,转换为相应的数值;否则返回NaN(注意与parseInt()函数的区别,324abc返回NaN);空字符串''返回0。
  3. undefined转换为NaNnull转换为0。
  4. 对对象通常返回NaN,但包含单个值的数组除外。

注意,Number()parseInt()都自动过滤前导空格后后置空格。

Number()方法的转换机制是先尝试调用valueOf(),然后尝试toString();尝试均失败后报错。

String()

将任意类型的值转换为字符串。

  1. 数值转换为相应字符串。
  2. 字符串转换后仍为原来的值。
  3. true转换为'true'false转换为'false'
  4. 对象返回代表对象的字符串,如[object Object]

String()方法的转换机制与Number()相似,只是先尝试调用toString(),然后尝试valueOf()。尝试失败后则报错。

Boolean

除以下内容外转换结果均为true

  1. undefined
  2. null
  3. 0, -0, +0
  4. NaN
  5. ''

因此所有对象的转换结果都为true,包括Boolean(new Boolean(false))对象。

自动转换

预期为何种类型,就自动转换为何种类型。

含有字符串的二元加法运算,算子均转换为字符串。其他运算符将算子转换为数值,存在将两侧的算子都转换为数值的情况。

注意一元运算符也会将算子转为数值

+true;   // 1
+'abc';  // NaN