JS知识点梳理(1)-基本概念

语法

区分大小写

ECMAScript 中的一切(变量、函数名、操作符)都区分大小写

标识符

标识符,指变量、函数、属性名,或函数的参数。它是按照以下规则组合起来的一个或多个字符:

  • 第一个字符必须是一个字母、下划线(_)或者一个美元符号($)
  • 其他字符可以是字母、下划线、美元符号、数字。

按照惯例,ECMAScript 标识符采用驼峰大小写格式,这是为了与 ECMAScript 内置的函数和对象命名格式保持一致

严格模式

严格模式(strict mode)是为 JS 定义了一种不同的解析和执行模式,且对正常的 JS 语义做了些更改,消除 JS 语法中一些不合理,不严谨之处,减少一些怪异行为。

    1. 严格模式通过抛出错误来消除一些原有静默错误
    1. 严格模式修复了一些导致 JS 引擎难以执行优化的缺陷,提高了运行效率
    1. 严格模式禁用了在 ECMAScript 的未来版本中可能会定义的一些语法

如何开启严格模式

  • "use strict";语句放在 JS 文件的开头,为整个 JS 文件开启严格模式
  • "use strict";语句放在函数体所有语句之前,为函数开启严格模式

严格模式中的变化

将过失错误转成异常

JS 起初被设计为能使新人开发更易于上手,所以有时候会给本来错误操作赋予新的不报错的语义(non-error semantics)。

  • 严格模式下,无法意外创建全局对象,抛出ReferenceError

    1
    2
    "use strict";
    a = 12; // ReferenceError: a is not defined
  • 严格模式下,引起静默失败(silently fail,即不报错也无任何效果)的赋值操作抛出异常。引起静默失败的赋值操作:

    • 给不可写的属性赋值

    • 给只读属性赋值

    • 给不可扩展对象的新属性赋值

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      "use strict";
      // 给不可写的属性赋值
      var obj = {};
      Object.defineProperty(obj, "x", { value: 20, writable: false });
      obj.x = 12; // TypeError: Cannot assign to read only property 'x' of object '#<Object>'

      // 给只读属性赋值
      var obj1 = {
      get x() {
      return 12;
      },
      // set x(value) {}
      };
      obj1.x = 32; // TypeError: Cannot set property x of #<Object> which has only a getter

      // 给不可扩张对象的新属性赋值
      var obj2 = {};
      Object.preventExtensions(obj2);
      obj2.x = 22; // TypeError: Cannot add property x, object is not extensible

  • 严格模式下,试图删除不可删除的属性时会抛出异常

    1
    2
    3
    4
    "use strict";
    delete Object.prototype; // TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
    delete c; // SyntaxError: Delete of an unqualified identifier in strict mode.

  • 严格模式下,函数中重命名参数被认为时语法错误

    1
    2
    3
    4
    5
    6
    "use strict";
    function sum(a,a,b) {
    return a + a + b;
    }
    // SyntaxError: Duplicate parameter name not allowed in this context

  • 严格模式下,以0开头的八进制语法被认为语法错误,可以使用0o前缀来表示八进制数

    1
    2
    3
    "use strict";
    var b = 012; // SyntaxError: Octal literals are not allowed in strict mode.
    var c = 0o12; // 10
  • 严格模式下,禁止给基本数据类型值设置属性,抛出 TypeError

    1
    2
    3
    4
    "use strict";
    false.age = 12; // TypeError: Cannot create property 'age' on boolean 'false'
    (15).age = 12; // TypeError: Cannot create property 'age' on number '15'
    "jiang".age = 12; // TypeError: Cannot create property 'age' on string 'jiang'
简化变量的使用

严格模式简化了代码中变量名字映射到变量定义的方式。JS 有些情况使得代码中名字到变量定义的基本映射只有在运行时才产生,严格模式移除了大多数这种情况的发生,所以编译器可以更好的优化严格模式的代码。

  • 严格模式下,禁用with.使用with所引起的问题是:块内的名称可以映射到with传进的对象属性,也可以映射到包含该块的作用域内变量,甚至全局变量。这一切都在运行时决定的,在代码运行之前无法得知。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    "use strict";
    var obj ={
    x: 12;
    }
    var x = 17;
    with(obj) { // // SyntaxError: Strict mode code may not include a with statement
    cosole.log(x);
    }
    // 如果没有开启严格模式,with中的x会执行全局的那个x,还是obj.x?
    // 如果不运行代码,则无法得知,因此,这样的代码让引擎无法进行优化,速度也就会变慢
  • 严格模式下,eval不在为上层范围引入新变量。

    1
    2
    3
    4
    (function doSomething() {
    eval('var x = 20');
    console.log(x); // ReferenceError: x is not defined
    })();
arguments变的简单
  • 严格模式下,参数的值不会随arguments对象的改变而变化。arguments对象会保存函数被调用时的原始参数,arguments[i]的值不会随着与之相应的参数的值的改变而变化
    1
    2
    3
    4
    5
    6
    function f(a) {
    "use strict";
    a = 42;
    return [a, arguments[0]];
    }
    console.log(f(17)); // [42, 17]
  • 严格模式下,不再支持arguments.callee.正常模式下,arguments.callee指向当前正在执行的函数。
    1
    2
    3
    4
    (function abc() {
    "use strict";
    return arguments.callee; // TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
    })();
更”安全的”JavaScript
  • 对于一个严格模式下的函数,指定的this不再被强制转换为一个对象,this值始终是指定的值,无论指定的是什么值.在非严格模式 下,使用call,apply,bind方法时,用undefined或者null指定this,其this值将自动转换为全局对象window或者global

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //  没有开启严格
    function func() {
    return this;
    }
    function func2() {
    "use strict";
    return this;
    }

    // 未开启严格模式
    console.log(func.call()); // global {...}
    console.log(func.call(2)); // Number {[[PrimitiveValue]]: 2}
    console.log(func.call(undefined)); // global {...}
    console.log(func.apply(null)); // global {...}
    console.log(func.bind(true)()); // Boolean {[[PrimitiveValue]]: true}

    // 开启严格模式
    console.log(func2.call()); // undefined
    console.log(func2.call(2)); // 2
    console.log(func2.call(undefined)); // undefined
    console.log(func2.apply(null)); // null
    console.log(func2.bind(true)()); // true

语句

ECMAScript 中的语句是以一个分号结尾;如果省略分号,则由解析器确定语句的结尾,但建议在任何时候都不要省略分号。它可以避免很多错误,如不完整的输入,更放心的通过删除多余空格来压缩代码。另外,加上分号也会在某些情况下提高代码性能,省去了解析器推测应该在哪添加分号的时间。

关键字和保留字

关键字用于表示控制语句的开始、结束,或者用于执行特定操作等。保留字表示将来有可能被用作关键字。二者都不能用作标识符。

变量

  • ECMAScript 的变量是松散类型的,即可以用来保存任何类型的数据。
  • 每个变量仅仅是一个用于保存值的占位符而已。
  • 省略var,let,const操作符,定义的变量,会成为全局变量。

数据类型

5 种基本数据类型: Undefined,Null,Boolean,Number,String
1 种复杂数据类型: Object ,包含DatafunctionArray等。
ES6 新增数据类型: Symbol,表示独一无二的值,可以用作对象的属性名,保证不会与其他属性名产生冲突。

typeof操作符

typeof操作符的操作数可以是变量,也可以是数值字面量,是一种用来检测给定变量的数据类型的手段,可能返回以下字符串:

  • “undefined” —- 未定义
  • “boolean” —- 布尔值
  • “string” —- 字符串
  • “number” —- 数值
  • “object” —- 对象或null(因为null被认为是一个空的对象引用,所以返回”object”)
  • “function” —- 函数

Undefined 类型

  • Undefined 类型只有一个值,即undefined,表示未经初始化的变量的值。
  • 另外需要注意,包含undefined值的变量和尚未声明的变量是不一样的,即使使用typeof操作符检测都会返回undefined。但传递给函数尚未声明的变量会报错。

Null 类型

  • Null 类型也只有一个特殊的值null.
  • null值表示一个空对象指针,这也是typeof null返回”object”的原因
  • 只要意在保存对象的变量还没有真正的保存对接,就应该明确的将该变量初始化为null
  • nullundefined之间的相等操作符(==)返回true

Boolean 类型

  • 对于任何数据类型的值 调用Boolean()函数,总会返回一个 Boolean 值。具体转化规则

    数据类型 转化为 true 的值 转化为 false 的值
    Boolean true false
    String 任何非空字符串 “”(空字符串)
    Number 任何非零数值 0 和 NaN
    Object 任何对象 null
    Undefined undefined

Number 类型

各进制表示

1
2
3
4
var decimalNum = 10;
var octalNum = 0o12;
var hexNum = 0xA;
var binaryNum = 0b1010;

数值范围

  • ECMAScript 表示的数值范围,Number.MIN_VALUE,Number.MAX_VALUE之间.超出范围的值被自动转化为-InfinityInfinity
  • isFinite()函数,判断参数是否位于最小和最大的数值之间。

数值转换

3 个函数可以将非数值转换为数值:Number(),parseInt(),parseFloat()

  • Number()函数可应用与任何数据类型,具体转换规则:
    • Boolean 值,true,flase 分别转换为 1,0
    • 数字值,返回值不变
    • null 值,返回 0
    • 字符串,则按以下规则:
      • 如果字符串只包含数字,则将其转换为十进制数值,忽略前导的零
      • 如果字符串包含有效的浮点格式,则转换为对应的浮点数值
      • 如果字符串包含有效的十六进制格式,”0xf”,转换为相同大小的十进制数值
      • 如果字符串是空的,转换为 0
      • 如果字符串中包含除上述格式之外的字符,则转换为 NaN
    • 对象,调用对象的 valueOf(),然后按照以上规则转换返回的值,如果结果为 NaN,则调用对象的toString()方法,然后按照以上规则转换返回的字符串值。
  • parseInt()函数,仅用于将字符串转换为数值。
    • 忽略字符串前面的空格,直到找到第一个非空格字符。如果第一个字符不是数字字符或负号,则返回 NaN。
    • 如果第一个字符是数字字符,会继续解析第二个字符,直到解析完所有后续字符或遇到一个非数字字符
    • 为了消除 ECMAScript 3 和 5 之间,解析八进制字面量的字符串时存在的分歧,可以为paeseInt()提供第二个参数:转换时使用的基数(多少进制):例如:parseInt("0fAF",16)
  • parseFloat()函数只解析十进制值,因此没有第二参数指定基数。

NaN

  • NaN,即非数值(Not a Number),表示一个本来要返回数值的操作数,但未返回数值的情况。
  • 任何涉及NaN的操作都会返回NaN
  • NaN与任何值都不相等,包含NaN本身
  • isNaN()函数,确定参数是否”不是数值”

String 类型

  • String 类型用于表示 0 或多个 16位Unicode字符组成的字符序列,即字符串
  • String 数据类型也包含一些特殊的字符字面量,也叫转义序列
  • \xnn,以十六进制代码 nn 表示一个字符,(n 为 0-F)。\x41表示”A”
  • \unnnn,以十六进制代码 nnnn 表示一个 Unicode 字符,(n 为 0-F),\u0061表表示”a”

字符串特点

ECMAScript 中字符串是不可变的,字符串一旦创建,它们的值就不能改变。要改变莫格变量保存的字符串,首先要先销毁原来的字符串,然后再用另一个包含新字符串填充该变量。

字符串转换

  • 数值,布尔值,对象,字符串值都有toString()方法,nullundefined值没有该方法
  • 如果不知道要转换的值是不是nullundefined情况下,可以使用转型函数String(),按以下规则:
    • 如果值有toString()方法,则调用该方法并返回结果
    • 如果值是 null,则返回”null”
    • 如果值是 undefined,则返回”undefined”

Object 类型

Object 类型是所有它的实例的基础,JS 中的所有对象都来自Object。即所有的对象从Object.prototype继承属性和方法。

  • constructor:保存着用于创建当前对象的函数(构造函数)的引用
  • hasOwnProperty(propertyName):返回一个布尔值,表示某个对象实例是否包含指定的属性,而且此属性非原型链继承的。其参数的属性名必须以字符串形式指定。
  • isPrototypeOf(object):返回一个布尔值,表示指定的对象是否在当前对象的原型链中
  • propertyIsEnumerable(propertyName):返回一个布尔值,表示指定的属性是否可枚举,能否使用for-in语句枚举,但是通过原型链继承的属性除外。
  • toString():返回对象的字符串表达
  • toLocaleString():根据执行环境的地区,返回对应的字符串表示
  • valueOf():返回指定对象的原始值。每个内置的核心对象都会覆盖此方法以返回适当的值。例如Date对象的valueOf()方法,返回自 1970/01/01 开始计的毫秒数

函数

  • 可以向 ECMAScript 函数传递任意数量的参数,在函数体内可以通过arguments对象来访问。
  • arguments对象是一个类数组对象,它不是 Array 的实例
  • 由于不存在函数签名的特性,ECMAScript 函数不能重载。