机制和原理

JavaScript是一门非常简练并且功能强大的脚本语言,其机制和原理具有非常与众不同的特点。

 

一切都是对象

JavaScript中,数值、字符串、数组、函数等一切都属于对象(Object)。

与其他语言一样,JavaScript仍然支持如下所示的原始数据类型及相应的字面量定义方式:

  • 数值型
    如:3、-2、3.14
  • 字符串型
    如:“Hi,world!”、“china”
  • 布尔型
    如:true、false

但与一般语言不同的是,基于一切都是对象的思想,JavaScript语言引擎会在程序执行时对以上原始数据类型自动创建相应的包装对象,从而可以象对象一样调用其对象方法。

  • 数值型 –> Number
  • 字符串型–> String
  • 布尔型–> Boolean

例如,String对象都拥有返回字符串长度的length属性,如果访问“Hi,world!”.length、 将获得返回值9。

而且,JavaScript的对象模型非常简单,JavaScript中的对象就是个键/值对的集合。

这里的「键」不限于字符串类型,也可以是数值或其他对象。

事实上,JavaScript中的数组(Array),本质上也是一个键/值对的集合,自然索引也是作为属性名(键)存在的。

对象基于原型

Java或C++等基于类的面向对象语言都包含有两个基本概念:类(Class)和实例(Instance)。类是一个抽象的模板,比如Employee类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

而JavaScript的面向对象的基本概念是原型(Prototype)。对象不分类和实例,但对象可以将其他的对象作为自己的原型,然后根据需要定义独自的属性。

运行期,JavaScript语言引擎会为所有的对象维护一个原型链,原型链的顶端是Object对象。

当对象被访问属性时,语言引擎会先查找对象本身,对象本身不存在该属性时,然后按照原型链从下到上依次查找。这就是JavaScript语言中的继承机制。

ECMAScript6虽然也引入了类(Class),但这并不意味着JavaScript在原型机制之外导入了一个类似于C++「类」的新机制。

ECMAScript6中的类仅仅是提供了一个更简单明了的语法方法用于定义构造函数,本质上就是构造函数,这也是其常常被说成是语法糖的缘由。

完全动态语言

JavaScript是一个完全动态的语言,这里包含以下三个意思:

  1. JavaScript是一个动态类型语言
  2. JavaScript是一个弱类型语言
  3. JavaScript是一个动态编程语言

其中,动态类型语言和动态编程语言是两个不同的概念,本身并没有关联性。

动态类型语言

动态类型语言(Dynamically Typed Language)指的是在运行期而不是在编译期对类型进行检查的一类语言。

  • 备注:
    作为解释语言的JavaScript等语言,其编译期可以理解成将脚本加载并转换为内部可执行代码这样一个过程。

属于动态类型语言的还有PHP、Ruby、Python等。

与动态类型语言相对的就是静态类型语言(Statically Typed Language),C#、Java、TypeScript等就属于这类语言。

弱类型语言

弱类型语言具有以下特点:

  1. 变量没有类型,可以被赋予不同类型的值
  2. 计算时不同类型的值会自动进行转化

同属动态类型语言的PHP、Ruby、Python中,PHP、Ruby也属于弱类型语言,而Python因为变量在第一次被赋值后,其类型便已被确定下来,另外计算时必须强制指定类型转化,因此通常被认为是强类型语言。

动态编程语言

动态编程语言(Dynamic Programming Language)指的是能够在运行中动态改变其程序结构,包括增加新的函数、类型等的一类语言。 JavaScript里可以在函数里嵌套函数,如下例所示,嵌套函数f2就是在外面的f1()函数被调用时才创建的,这也是JavaScript闭包实现的基础。

function f1(x) {
  function f2() {
    return x;
  }
  return f2;
}
f1(3);

部分支持函数编程

JavaScript部分具有函数语言的特点,函数语言本身可能比较复杂,但对于JavaScript来说,您只要掌握以下3点就可以了:

  • 所有的函数都有返回值
  • 函数没有副作用
  • 函数也可以当作值进行处理

函数都有返回值

所有的函数都返回值,如果没有明确的代码实现,函数的返回值就是undefined。

函数没有副作用

函数没有副作用,包含以下两点:

  • 函数不应改变外部的变量值
  • 函数不应改变引用传递的参数的值

函数也是值

函数也是对象,一种可以被执行的特殊对象。 函数能够当作值进行处理,因此関数的参数可以是另外一个函数,函数的返回值也可以是一个函数。

闭包

闭包是函数式语言中一个非常重要和强大的功能。JavaScript在函数对象被创建时会把当时的执行环境保存起来,形成一个闭包作用域,函数每次执行时都能够访问这个作用域中的变量。因此,闭包通常用来创建内部变量,使得这些变量不能被外部随意修改,同时又可以通过指定的函数接口来操作。