JavaScript面向对象系列:二、函数

在js中,函数气死就是对象。使函数不同于其他对象的决定性特点是函数存在一个被称为 [[Call]] 的内部属性。内部属性无法通过代码访问而是定义了代码执行时的行为。es为js的对象定义了多种内部属性,这些内部属性都用双重中括号来标注。

[[Call]] 属性是函数独有的,表明该对象是可以被执行的。由于仅函数拥有该属性,es定义typeof操作符对任何具有 [[Call]] 属性的对象返回”function”。这在过去曾导致一些问题,因为某些浏览器曾经在正则表达式中包含 [[Call]] 属性,导致后者被错误鉴别为函数。现在,所有的浏览器行为都一致。typeof 不会再将正则表达式鉴别为函数了.

声明还是表达式

函数具有两种字面形式

第一种:函数声明

function add(num1,num2){
return num1 + num2;
}

第二种:函数表达式

var add = function(num1,num2){
return num1 + num2;
}

这两种看起来相似,实际上有一个非常重要的区别

函数名声形式的会被提升至上下文(context)顶部,而函数表达式不会

所以就会有下面的情况

var result = add(5,5);

function add(num1,num2){
return num1 + num2;
}

这种实际上是能正确运行的,这是因为函数声明被提升至上下文顶部,好像被写成

function add(num1,num2){
return num1 + num2;
}

var result = add(5,5);

但是下面这种就会报错

var result = add(5,5);

var add = function(num1,num2){
return num1 + num2;
}

因为函数表达式不会被提升,所以上面执行时找不到函数。
不过,只要你始终在使用函数前定义他们,你就可以随意使用者两种字面形式.

参数

js的函数另一个独特之处在于你可以给函数传递任意数量的参数却不造成错误。因为函数参数实际被保存在arguments的类数组对象中。

函数的命名参数只不过是为了方便使用,并不是真正的限制了该函数可接受参数的个数。

函数的命名参数都是函数的期望参数,函数的length属性只会显示出期望参数的个数。

例如

情况一

function reflect(value){
return value;
}

console.log(reflect("1")); // "1"
console.log(reflect("1"),25); //"1"
console.log(reflect.length); //1

情况二

function reflect(){
return arguments[0];
}

console.log(reflect("1")); // "1"
console.log(reflect("1"),25); //"1"
console.log(reflect.length); //0

重载

大多数面向对象语言支持函数重载,它能让一个函数具有多个 函数签名(函数签名由函数的名字,参数的个数以及其类型组成) ,因为js可以接受任意数量的参数且没有类型限制,所以js没有函数重载。

例如

function sayMessage(message){
console.log(message);
}

function sayMessage(){
console.log("Default message");
}

sayMessage("Hello"); //"Default message"

这里为什么是 “Default message”,可以用对象来帮助理解

var sayMessage = new Function("message","console.log(message);");
sayMessage = new Function("message","console.log(\"Default message\");");
sayMessage("Hello!"); //Default message

但是js可以模仿函数重载

例如

function sayMessage(message){
if(arguments.length === 0){
message = "Default message";
}
console.log(message);
}
sayMessage("Hello!"); //Hello!

总结

js函数的独特之处在于它们同时也是对象,也就是说它们可以被访问、复制、覆盖,就像其他对象一样。js中的函数和其他对象最大区别在于函数对象有一个特殊的内部属性 [[Call]],包含了该函数的执行指令。typeof 操作符会在对象内部查找这个内部属性,如果找到,就返回 “function”

函数字面形式有两种:声明和表达式。函数声明会被提升至上下文顶部,而函数表达式不会。但是函数表达式可以用于任何可以使用值的地方,例如赋值语句、函数参数或者另一个函数的返回值。

函数是对象,所以存在一个构造函数 Function。

发表评论

电子邮件地址不会被公开。 必填项已用*标注