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 这个数组来便利所有的参数。

posted @ 2017-01-04 22:47  shelfy  阅读(170)  评论(0编辑  收藏  举报