js~函数声明与函数表达式

1 概述

js是一门动态语言,动态语言只有运行时的概念。运行时处理的一切都是对象,包括对象赋值、对象执行;这些对象是有区别的,如函数对象可以使用函数操作符'()'调用,而像{}、[]等就不能使用函数操作符。 故在运行时,语言设计上的不同成份会有不同的处理方式。本文的关注点是运行时函数声明和函数表达式的不同处理。

2 概念

js定义函数的方式有2种,一是函数声明,二是函数定义。

2.1 函数声明

独立的函数体定义,结尾不加分号; 如,function 函数名称 () {函数体}

2.2 函数表达式

在表达式中赋给变量,或者在对象中赋给对象属性; 如,var 变量 = function [函数名称] () {}; //函数名称可以不定义,作为匿名函数

3 示例

测试环境: node.js v0.9.5-pre

/**
 * Auther: dzh <dzh_11@hotmail.com>
 * Version: t_func_expr_decl.js,v 1.0 2013/04/30 14:47:04
 * Runtime: node.js v0.9.5-pre
 */

/*函数声明*/
console.log("------------Test 1-------------");
function func_decl () {
    function func_decl_inner () { return "func_decl_inner";} //函数声明可以嵌套定义
    return "func_decl" + "&" + func_decl_inner.name;
}
console.log(func_decl.name) //输出“func_decl”,说明函数声明也是对象
console.log(func_decl()); //输出“func_decl&func_decl_inner”

console.log("------------Test 2-------------");
/*函数表达式*/
var func = function () {
    function func_decl_inner () { return "func_decl_inner";} //函数表达式里可以定义函数声明
    return "anonymous function" + "&" + func_decl_inner.name;
};
console.log(func());  //输出“anonymous function&func_decl_inner”

// 作为函数参数调用
console.log("------------Test 3-------------");
var func_invoked = function (func) {
    try{
        return func();  
    }catch (e){
        var func_type = typeof func;
        return "func's type is "+ func_type + ", but it need function type. " +  e.toString();
    }
};
console.log(func_invoked(func)); //输出“anonymous function&func_decl_inner”
console.log(func_invoked(func_decl)); //输出“func_decl&func_decl_inner”

// 赋值给变量
console.log("------------Test 4-------------");
var func_ref = func;
var func_decl_ref = func_decl; //函数声明赋值给变量,并被作为函数调用
console.log(func_decl_ref()); //输出“func_decl&func_decl_inner”
console.log(func_ref()); //输出“anonymous function&func_decl_inner”

// 赋值给对象属性
console.log("------------Test 5-------------");
var obj = {
    //  function func_decl () {return "func_dec"} //错误“SyntaxError: Unexpected identifier”,对象内部不能定义函数声明
    func: func,
    func_decl: func_decl, //函数声明可以赋值给对象属性,并作为函数被调用
    func_def: function func_def (){ return "func_def";}
};
console.log(obj.func_decl()); //输出“func_decl&func_decl_inner“
console.log(obj.func()); //输出“anonymous function&func_decl_inner”
console.log(obj.func_def()); //输出“func_def”  

4 总结

  • 函数声明和函数表达式就实质而言没有不同,都是函数对象,都能赋给变量、对象属性和作为函数参数,然后用函数操作符调用执行。

这点和《JavaScript Patterns》中译名《JavaScript模式》62页“声明Vs表达式: 名称和变量声明提升“中的”它们的定义不能分配给变量或属性,也不能以参数形式出现在函数调用中。“不符。 我觉得这和js解释器有关系,但从语言设计角度,声明和表达式直接定义在处理上应该是保持一致的,因为它们都是函数对象。

  • 函数声明只能出现在全局对象、函数声明中。函数声明中可以定义函数声明,内部声明的作用域是父函数对象。

函数声明不能出现在其他对象定义中(如{}),我觉得原因是简化对象语法设计,{对象属性:函数表达式}的形式满足内部定义函数的需求,同时保持对象key:value形式的一致性。

5 参考

《JavaScript模式》 O'REILLY Stoyan Stefanov著 60-62页 “消除术语的歧义” “声明Vs表达式: 名称和变量声明提升“

Date: 2013-04-30T17:42+0800

Author: dzh

Org version 7.9.2 with Emacs version 23

Validate XHTML 1.0
posted on 2013-04-30 17:51  戴忠  阅读(389)  评论(0编辑  收藏  举报