其他分享
首页 > 其他分享> > 6.5 函数是一种对象

6.5 函数是一种对象

作者:互联网

函数也是一种对象。从内部结构来看,它继承于 Function 对象。可以像下面这样通过 constructor 属性验证。

function hzh() {} // 函数的内容无关紧要,因此留空
console.log("使用constructor属性验证函数hzh:");
console.log(hzh.constructor);
[Running] node "e:\HMV\JavaScript\JavaScript.js"
使用constructor属性验证函数hzh:
[Function: Function]

[Done] exited with code=0 in 2.145 seconds

将匿名函数赋值给某个变量,与将 Function 对象的引用赋值给某个变量,在本质上是相同的,仅仅是表述方式的不同而已。在通常的语境中,函数的概念等价于 Function 对象的引用。因此,函数的声明与 Function 对象的生成也是等价的。

从形式上来看,代码清单 6.8 中例举的 4 种方式差异巨大,不过从整体上来看,这些代码的功能是类似的,都是先生成一个实体(即没有名字的对象),之后将其与引用了它的名称相结合。

代码清单 6.8 从整体上来看,都是生成了实体并赋予一个引用了该实体的名称。

var hzh = {};
var hzh = new hzhClass();
var hzh = function() {};
function hzh() {}

可以像下面这样,通过对 Function 函数进行构造函数调用,来生成一个 Function 对象。不过这种用法并不多见。

// 函数声明(Function对象的生成)
var hzhSum = Function('a', 'b', 'return Number(a) + Number(b);');

// 最后一个参数是函数体。它之前的参数都是函数的形参。

// 函数的调用
console.log(hzhSum(3, 4));
[Running] node "e:\HMV\JavaScript\JavaScript.js"
7

[Done] exited with code=0 in 0.175 seconds

由于函数是一种对象,因此自然可以读写 Function 对象的属性。

function hzh() {} // 函数内部的内容对读写操作不会造成影响,因此在此使用了一个空函数
hzh.huangzihan = '黄子涵';

console.log('输出hzh对象的huangzihan属性:');
console.log(hzh.huangzihan);
[Running] node "e:\HMV\JavaScript\JavaScript.js"
输出hzh对象的huangzihan属性:
黄子涵

[Done] exited with code=0 in 0.199 seconds

如果对属性赋值以其他的函数,就相当于为该函数(对象)添加了方法。

function hzh() {} // 函数内部的内容对读写操作不会造成影响,因此在此使用了一个空函数
hzh.huangzihan = '黄子涵';

hzh.huangchunqin = function() {
    console.log('黄春钦是黄子涵的弟弟。');
}

console.log("输出hzh对象的huangchunqin属性:");
console.log(hzh.huangchunqin);
console.log("");
console.log("调用hzh对象的huangchunqin方法:");
console.log(hzh.huangchunqin());
[Running] node "e:\HMV\JavaScript\JavaScript.js"
输出hzh对象的huangchunqin属性:
[Function]

调用hzh对象的huangchunqin方法:
黄春钦是黄子涵的弟弟。
undefined

[Done] exited with code=0 in 0.201 seconds

在这种情况下,一个变量与其所引用的对象之间的关系可能有些复杂,不过只要记住 Function 对象含有一些可执行代码的这一事实,就不会有什么问题(图 6.2)。

图 6.2 变量 f 所引用的 Function 对象(Function 对象中含有引用了其他函数的变量)

image

函数名与调试的难易度

对象从本质上来说是不具有名称的。由于函数也是一种对象,所以 Function 对象也没有名称。从原则上来说这没有错,不过有必要再对此做一些补充说明。在通过函数声明语句以及匿名函数表达式对函数名进行指定时,在 Function 对象的内部储存了其表示名称。

在下面的代码中,hzh_name 的部分将作为 Function 对象的表示名称。

function hcq_name() { ... }           // 函数声明语句
var hzh = function hcq_name() { ... } // 匿名函数表达式

“函数的表示名称”,使用这一名称为了与通常的函数名的概念相区分。

函数名是具有 Function 对象的引用的变量名。而“函数的表示名称”则是被储存于 Function 对象内部的名称。虽然无法直接通过“函数的表示名称”来调用函数,不过对于使用函数声明语句的情况,由于在 function 之后所写的名称就是其函数名,所以从表面上来看并没有区别。然而在内部,函数名与函数的表示名称是分别存在的。下面的代码没什么实际意义,不过可以对这一点进行验证。

function hcq() {} // 函数声明语句。由于内部的内容对调用操作不会造成影响,而在此使用了一个空函数
var hzh = hcq;    // 这样一来就可以通过函数名 hzh 对其进行调用
hcq = null;       // 将变量 hcq 的值置为 null
console.log(hzh); // “函数的表示名”仍然为 hcq
[Running] node "e:\HMV\JavaScript\JavaScript.js"
[Function: hcq]

[Done] exited with code=0 in 0.177 seconds

在对 Function 对象进行 console.log() 等操作时会使用函数的表示名称。例如,在显示 constructor 属性所引用的 Function 对象时,所表示的名称即函数的表示名称。而在调试中显示调用栈时,函数的表示名称将发挥更大的作用。

在 JavaScript 程序设计中,与函数声明语句相比,使用匿名函数表达式的情况似乎越来越多。这时,常常会省略写在 function 之后的函数的表示名称。但因为在调试过程中函数的表示名称是非常有用的,所以还请对这一问题多加考虑。

标签:Function,console,函数,对象,hzh,6.5,log
来源: https://www.cnblogs.com/Huang-zihan/p/16330011.html