函数
函数对象
首先来理解一下什么事对象:ECMA-262是这样定义的“无序属性的集合,其属性可以包含基本值、对象或者函数”,也就是说,对象是‘名/值’对的集合。
var person=new Object();person.name="Jake";person.age=18;person.sayName=function(){ alert(this.name);}
上面的例子创建了一个名为person的对象,并为它添加了两个属性:name、age和一个方法sayName。其中sayName用于显示this.name(将被解析为person.name)的值。
函数字面量
我们来看一段代码:
var add=function(a,b){ return a+b;}
函数字面量包含4个部分,分别是:
- 保留字 function
- 函数名 add
- 参数 a、b
- 语句 return a+b;
函数字面量可以出现在任何允许出现的地方,也可以定义在其他函数中。一个内部函数除了可以访问自己的参数和变量,同时它也能自由地访问它的父函数的变量和参数。通过函数字面量创建的函数对象包含一个连接到外部上下文的链接。这被称为闭包
闭包
闭包这个概念是js这门语言中一个非常重要而且是很难掌握的知识点!
这里只能浅显地解释一下什么是闭包我们用一些代码来解释这个定义:function foo(){ var a=2; function bar(){ console.log(a); } return bar;}var baz=foo();baz();//2 <--这就是闭包的效果
函数bar()的词法作用域能够访问foo()内部作用域,然后将bar()函数本身当作一个值类型进行传递。
在foo执行后,其返回值 bar()赋值给变量baz并调用baz(),实际上只是通过不同的标识符引用调用了内部的函数bar()。在foo执行后,foo内部作用域不会被销毁,因为一直都是bar()本身在使用,所哟foo内部作用域依然存在且能够一直存活,以供bar随时进行引用。bar依然对该作用域保持引用,而这个引用就叫作闭包。函数作用域
作用域的作用:控制着变量与参数的可见性以及生命周期。
定义在函数内部的参数和变量在函数外部是不可见的,而在一个函数内部任何位置定义的变量,在函数内部任何位置都可见。var f00=function(){ var a=3,b=5; var bar=function(){ var b=7,c=11; //此时a=3,b=7,c=11; a+=b+c; //此时a=21,b=7,c=11; }; //此a=3,b=5,c没有定义; bar(); //此时a=21,b=5;}
调用
调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。js提供了四种调用模式:方法调用模式、函数调用模式、构造器调用模式以及apply调用模式。
- 方法调用模式
当一个函数被保存为对象的一个属性是,我们称之为方法。当一个方法被调用时,this被绑定到该对象,当对象与方法用“.”来连接时,那么它就被当作一个方法来调用了。
var person={ name:"Jake", age:18, sayAge:function(age){ this.age=age; }};person.sayAge(19);docunment.writeln(person.age);//19
2.函数调用模式
当一个函数并不是一个对象的属性时,那么它就是被当作一个函数来调用的
var myobject={}//添加一个新的方法myObject.do=function(value){ this.value=value; var that=this; var helper=function(){ that.value=that.value+that.value; }; helper();}myObject.do(3);console.log(myObject.value)//6
这里面遇到一个问题,就是在helper函数内部的this指向的时这个函数本省,而不是全局对象。我们找到一个很好的解决方法,那就是将this赋值给一个全新的变量that,那么内部函数就可以访问到this,这样就避免了内部函数里面的this错误的绑定。
3 构造器调用模式
一个函数,如果创建的目的就是希望结合new前缀来调用,那就被称为构造函数
如果一个函数前面带上new来调用,那么就会创建一个连接到该函数的prototype(原型)成员的新对象,同时函数中的this会绑定到这个新对象中。var Myobject=function(string){ this.status=string;}Myobject.prototype.get_status=function(){ return this.status;}//创建实例var newObj=new Myobject("Hello !");console.log(newObj.get_status());//Hello !
这里要特别注意:按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。
4.Apply调用模式
Apply方法让我们构建一个参数组传递给调用函数。它允许我们选择this的值。Apply方法接受两个参数,第一个要绑定给this的值,第二个就是参数数组。
var array=[3,4];var sum=add.apply(null,array);//sum值为 7
var statusObj={ status:'Hello'};var status=Quo.prototype.get_status.apply(statusObj);//status值为‘Hello’
function SpeciallArray(){ var values=new Array(); values.push.apply(values,arguments); values.toPipedString=function(){ return this.join("|"); } return values;}var color=new SpeciallArray("blue","yellow","red");console.log(colo.toPipedString);//"blue|yellow|red"