你的位置:首页 > Java教程

[Java教程]JavaScript笔记(二):函数只是一种对象


上一篇随笔提到JS中有两种数据类型:原始类型和对象类型,但是我们还没有提到函数。实际上函数也是一种对象,准确地说函数应该叫做函数对象。下面从对象开始说起。

1. 对象和函数

 最简单的对象,是这样的:

var obj = {};

 我们创建了一个空对象。说它空是因为它没有任何自定义属性,但是实际上它还是有一些默认属性的,这些属性是从它的原型对象继承来的,比如constructor、toString和valueOf等。除此之外,ECMA-262中还定义了对象的一些内置属性,这些属性对JS语言来说是不可见的,也就是说跟我们的编程无关。但是简单地了解一下这些内置属性,对我们深入理解对象的内部机制是有益的。这些属性包括:[[Prototype]]、[[Extensible]]、[[Get]]、[[Put]]、[[HasProperty]]和[[Delete]]等,具体的含义在此不提,只需要知道,只要是对象,一定具有这些属性。

接下来,我们说一下函数。我们经常听人说“函数是JS中的一等公民,函数可以做参数,可以做返回值”。其实原因很简单,函数也是一种对象,是一种特殊的对象。它只是比普通的对象多了一些特殊的东西,所以看起来跟普通对象有所不同。那么,函数与普通对象比有哪些不同呢?

(1) 从语言规范或者说从JS引擎的角度来看,函数除了前面提到的那些内置属性外,还多了一些内置属性,包括:

  • [[Code]]:函数的代码,即函数体里面的那些语句。
  • [[FormalParameters]]:函数的形参列表。
  • [[Scope]]:词法环境(Lexical Environment),它确定了函数执行时所处的环境。这个东西很重要,跟我们经常听说的作用域链闭包有关系。
  • [[Call]]:执行代码,即在调用此函数时执行的动作。
  • [[Construct]]:构造一个新的对象的动作。拥有这个内置属性的函数被称为构造函数,通过new操作符可以用它来产生新的对象。
  • [[HasInstance]]:用来检测一个对象是否是此函数构造的。

(2) 由于函数是一种特殊的以及非常重要的对象,所以JS语言专门提供了特殊的语法来创建函数,即

// 函数声明function sayHello() {  console.log('Hello');  }// 函数表达式var sayHello = function () {  console.log('Hello');}

 当然,也可以用类似于创建普通对象的方式(即new+构造函数)来创建函数,即

var sayHello = new Function("console.log('Hello');");

 是不是跟普通对象的方式很像啊:

var data = new Date('2015/09/10');

 显然Function是一个非常特殊的构造函数,因为一般的构造函数只能创建普通对象,但是Function能创建一个函数对象。

(3) 函数是可调用的。我们通过函数调用表达式来调用一个函数,从而完成实现某种特定的功能,例如:

function add(x, y) {  return x + y;}var z = add(3, 4);console.log(z); // 输出5

 这也是我们使用函数最常见的目的。

2. 构造函数

其实上面已经顺带把构造函数也讲了。构造函数是指可以利用 new 操作符来创建对象的函数,这个过程是通过内置属性[[Construct]]实现的。比如Object就是一个构造函数:

var obj = new Object();

实际上,我们在程序里使用函数声明、函数表达式或Function创建出来的函数都是即使普通函数也是构造函数。它们既可以被调用以得到返回值或产生某种效果,也可以用new操作符来创建对象。但是从本质上讲构造函数比普通函数要更特殊一些。

另外为了进行区分,在命名时,前者通常首字母小写,后者通常首字母大写。举一个构造函数的例子:

function Person(name, age) {  this.name = name;  this.age = age;  }