一、函数的命名
函数使用function关键字来定义。它可以用在函数定义表达式或者函数声明语句里。在这两种形式中,函数定义都从function关键字开始。
1.表达式
var a = function(){};//函数表达式实际上就是声明了一个变量,然后把一个函数的对象赋值给它
2.函数声明
function a(){};
区别:函数声明,会将声明提前,在还未执行的时候就会解析,这样如果一个作用域有两个相同的函数名,那么值就会被覆盖,保存的是最后的那个,但是函数表达式就不会这样,它会在代码执行的时候被解析。
二、函数调用的模式
1.方法调用模式
在JavaScript中函数也是一种对象,函数可以作为对象的属性,此时函数也称为对象的方法。
var object={
op:1;
oq:2;
add:function(){
this.sum = this.op+this.oq;//this指代当前对象
}
}
onject.add();//作为方法调用,先调用方法,然后获取方法的值,执行object.rel;
object.rel;//结果是3
2.函数调用模式
function a(){};
a();//作为函数调用
**区别:**方法调用和函数调用的主要不同在于执行环境也就是上下文。
举例说明:
var o={ //对象o
m:function(){ //对象中的方法m()
var self=this; //将this值保存至一个变量中
console.log(this===o) //true,this就是对象o
f(); //调用嵌套函数f
function f(){
console.log(this===o); //false:this指向的是全局对象或者undefined
console.log(self===o); //true:self指向外部函数的this值
}
}
}
//调用
o.m();
此处特别要注意嵌套函数里面的this不是指向外层函数的this,如果想访问外部的this,需要将它保存在变量self中(当然可以随便命名),这个变量和内部函数都在同一个作用域中。
注意:
作为对象调用的时候this指向的是该对象;
作为函数调用的时候this指向的是全局变量,在浏览器中全局变量就是window,这里会隐式声明一个全局变量。
举例说明:
//这里写一个坐标平移的对象
var point = {
x : 0, //两个属性
y : 0,
moveTo : function(x, y) { //函数作为对象的方法调用
var moveX = function(x) { // 内部函数,作为函数调用
this.x = x; //this 绑定到了哪里?我们期望的是该对象的属性x
};
var moveY = function(y) { // 内部函数
this.y = y; //this 绑定到了哪里?
};
moveX(x); //调用(此处内部函数调用,隐式生成了一个全局变量x)
moveY(y); //调用
}
};
point.moveTo(1, 1);
point.x; //==>0 //原来对象的属性x和y并没有发生变化,说明之前的this指向的并不是外部的对象,而是全局变量
point.y; //==>0
x; //==>1
y; //==>1
针对这种情况,我们可以通过将外部this保存在一个变量中(因为在js中this是动态变化的)以下做出改进函数:
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
var that = this; ///////////////////特别注意
var moveX = function(x) {
that.x = x; //////////////////////////改变
};
var moveY = function(y) {
that.y = y; ///////////////////////////改变
}
moveX(x);
moveY(y);
}
};
point.moveTo(1, 1);
point.x; //==>1
point.y; //==>1
3.构造函数调用模式
如果函数或者方法前面带有关键字new,它就构成了构造函数调用,有个不成文的规定,构造函数的函数名首字母要大写。构造函数通常不使用return关键字,常用于初始化对象
function Point(x, y){
this.x = x;
this.y = y;
};
var point = new Point(1,2);//作为构造函数调用
凡是没有形参的构造函数都可以省略圆括号,如下是等价的:
var object = Object();
var object = Object;
4.apply或call调用模式
JavaScript中函数也是对象,这是js的特殊之处,那么我们知道对象有属性和方法,apply和call就是函数对象的方法。这两个方法允许切换函数执行的上下文环境(就是this绑定的对象),apply和call的功能相同,只是实现的时候call是将每个参数分别传入,而apply是将参数放进一个数组装入。
var func = function(arg1,arg2){
};
//这里的this是自己想要指定的上下文,可以是js的任何一个对象,这样就能改变上下文了。
func.call(this,arg1,arg2);
func.apply(this,[arg1],[arg2]);
举例说明:
我们使用构造函数生成了一个对象 p1,该对象同时具有 moveTo 方法;使用对象字面量创建了另一个对象 p2,我们看到使用 apply 可以将 p1 的方法应用到 p2 上,这时候 this 也被绑定到对象 p2 上。另一个方法 call 也具备同样功能,不同的是最后的参数不是作为一个数组统一传入,而是分开传入的。
function Point(x,y){//构造函数
this.x = x;
this.y = y;
this.moveTo = function(x,y){
this.x = x;
this.y = y;
};
};
var p1 = new Point(2,3);//构造函数调用
var p2 = { //创建一个对象字面量
x:0,//注意这里是逗号
y:0;
};
p1.moveTo(1,1);//调用方法
p1.moveTo.apply(p2,[5,4]);
下面这个更容易理解:
function hello(thing) {
console.log(this + " says hello " + thing);
}
hello.call("Yehuda", "world") //=> Yehuda says hello world