函数也是对象,使对象不一样于其它对象的决定性特色是函数存在一个被称为 [[Call]]
的内部属性。正则表达式
相似于[[Call]]
这种内部属性没法经过代码访问,他只是定义了代码执行时的行为。数组
ECMAScript为JavaScript的对象定义了多种内部属性,这些内部属性都用双重中括号来标注。浏览器
[[Call]] 属性是函数独有的,代表该对象能够被执行。因为仅函数拥有该属性,ECMAScript 定义 typeof 操做符对任何具备 [[Call]] 属性的对象返回 "function"。app
过去因某些浏览器曾在正则表达式中包含 [[Call]]
属性,致使正则表达式被错误鉴别为函数。函数
函数有两种字面形式:函数声明跟函数表达式。ui
二者的一个重要区别是:函数声明会被提高至上下文(要么是该函数被声明时所在的函数范围,要么是全局范围)的顶部。this
函数是JavaScript的一大重点。spa
基本上只要是可使用其余引用值的地方,你就可使用函数。也就是说,你能够像使用对象同样使用函数(由于函数原本就是对象)。指针
JavaScript函数另外一个独特之处在于你能够给函数传递任意数量的参数却不形成错误。调试
这是由于函数参数保存在类数组对象 arguments
中。
如同一个普通JavaScript数组,arguments能够自由增加来包含任意个数的值,这些值可经过数字索引来引用。
虽然arguments相似数组,可是Array.isArray(arguments)
返回 false
最后须要注意两点:
length
属性代表其指望的参数个数。大多数面向对象语言支持函数重载,它能让一个函数具备多个签名。函数签名由函数的名字、参数的个数及其类型组成。
而 JavaScript 能够接收任意数量的参数且参数类型彻底没有限制。这说明 JavaScript 函数根本就没有签名,所以也不存在重载。
function sayMessage(message){
console.log(message);
}
function sayMessage(){
console.log("Default Message");
}
sayMessage("Hello!"); // 输出"Default Message";
复制代码
在 JavaScript 里,当你试图定义多个同名的函数时,只有最后的定义有效,以前的函数声明被彻底删除(函数也是对象,变量只是存指针)。
var sayMessage = new Function("message", "console.log(message)");
var sayMessage = new Function("console.log(\"Default Message\");");
sayMessage("Hello!");
复制代码
固然,你能够根据传入参数的数量来模仿重载。
对象的值是函数,则该属性被称为方法。
JavaScript 全部的函数做用域内都有一个 this
对象表明调用该函数的对象。
在全局做用域中,this
表明全局对象(浏览器里的 window)。
当一个函数做为对象的方法调用时,默认 this
的值等于该对象。
this在函数调用时才被设置。
function sayNameForAll(){
console.log(this.name);
}
var person1 = {
name: "Nicholas",
sayName: sayNameForAll
}
var name = "Jack";
person1.sayName(); // 输出 "Nicholas"
sayNameforAll(); // 输出 "Jack"
复制代码
有3种函数方法运行你改变 this
值。
使用 call
或 apply
方法,就不须要将函数加入每一个对象——你显示地指定了 this
的值而不是让 JavaScript 引擎自动指定。
call
与 apply
的不一样地方是,call
须要把全部参数一个个列出来,而 apply
的参数须要一个数组或者相似数组的对象(如 arguments
对象)。
bind
是 ECMAScript 5 新增的,它会建立一个新函数返回。其参数与 call
相似,并且其全部参数表明须要被永久设置在新函数中的命名参数(绑定了的参数(没绑定的参数依然能够传入),就算调用时再传入其它参数,也不会影响这些绑定的参数)。
function sayNameForAll(label){
console.log(label + ":" + this.name);
}
var person = {
name: "Nicholas"
}
var sayNameForPerson = sayNameForAll.bind(person);
sayNameForPerson("Person"); // 输出"Person:Nicholas"
var sayName = sayNameForAll.bind(person, "Jc");
sayName("change"); // 输出"Jc:Nicholas" 由于绑定的形参,会忽略调用时再传入参数
复制代码
[[Call]]
,包含了该函数的执行指令。Function
构造函数。但这会使你的代码难以理解和调试,除非函数的真实形式要直到运行时才能肯定的时候才会利用它。