5-JS函数
函数
定义函数
JS中有3种定义函数的方法:
函数声明
用函数声明定义函数的方式如下:
function abs(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}
上述abs()
函数的定义如下:
function
指出这是一个函数定义;abs
是函数的名称;(x)
括号内列出函数的参数,多个参数以,
分隔;{ ... }
之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。
注意,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined。
函数表达式
用函数表达式定义函数的方式如下:
var abs = function(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}
在这种方式下,function (x) { ... }
是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs
,所以,通过变量abs
就可以调用该函数。
函数构造法
// 参数必须加引号
var add = new Function('x','y','return x+y');
add(2,3); // 5
一般不推荐用这种方法定义函数,因为这种语法会导致解析两次代码(第一次是解析常规ECMAScript代码,第二次是解析传入构造函数中的字符串),从而影响性能。
函数声明和函数表达式的差别
对于函数声明,JS解析器会在预解析阶段优先读取函数声明的代码,以确保函数能够被引用到;而对于函数表达式,只有在执行到相应的语句时才进行解析。在实际中,具体表现在:当使用函数声明的形式来定义函数时,可将调用放在函数声明之前,而使用函数表达式,这样做的话会报错。
add(1,2); // 3
function add(x, y) {
return x + y;
}
add(2,3); // 5
add(1,2); // 报错
var add = function(x, y) {
return x + y;
}
add(2,3); // 5
调用函数方式
1、普通调用
调用函数时,按顺序传入参数即可:
abs(10); // 返回10
abs(-9); // 返回9
由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:
abs(10, 'blablabla'); // 返回10
abs(-9, 'haha', 'hehe', null); // 返回9
2、方法调用
//定义一个函数
function hello(name) {
alert('hello,' + name);
};
var user = {};
//赋值给user的sayHi属性
user.sayHi = hello;
//方法调用
user.sayHi('张三');
3、构造函数调用
1.当使用new关键字创建一个对象时,即调用了构造函数。构造函数若没有形参,可以省略圆括号:
var obj = new Object();
//等价于
var obj = new Object;
2.调用构造函数,创建了一个新对象,这个新对象会成为该构造函数的调用上下文(this的值)
function User(name) {
this.name=name;
console.debug(this);
}
var user = new User('张三');
4、call和apply
call和apply的作用是改变函数执行时的上下文,即改变函数运行时的this指向。
一言不合贴代码:
function Person(name){
this.name = name;
}
Person.prototype = {
constructor: Person,
showName: function(){
console.log(this.name);
}
}
var person = new Person('Jeepeng');
person.showName(); // Jeepeng
var animal = {
name: 'cat'
}
// 1 call
person.showName.call(animal); // cat
// 2 apply
person.showName.apply(animal); // cat
二者的作用完全一样,区别只在于这两个函数接受的参数形式不同。
obj.call(thisObj, arg1, arg2, ...);
obj.apply(thisObj, [arg1, arg2, ...]);
一言不合贴代码:
function sum() {
var length = arguments.length;
var result = 0;
for(var i = 0; i < length; i++) {
result += arguments[i]; // 不严谨,仅为了说明问题
}
return result;
}
sum(1,2,3,4,5); // 15
sum.call(null, 1,2,3,4,5); // 15
sum.apply(null, [1,2,3,4,5]); // 15
当你的参数是明确知道数量时,用 call,而不确定的时候,用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来便利所有的参数。