JavaScript:Function类型

在JavaScript中,函数实际是对象。每个函数都是Function类型的实例,而且都与其他类型一样具有属性和方法。函数声明方式:

// 第一种:使用函数声明语法定义
function sum (num1, num2) {
    return num1 + num2;
}

// 第二种:使用函数表达式定义函数
var sum = function(num1, num2) {
    return num1 + num2;
};

// 第三种:构造函数
var sum = new Function("num1", "num2", "return num1+num2");

由于函数是对象,因此函数名实际上是一个指向函数的指针,不会与某个函数绑定。函数名与包含对象指针的其他变量没有什么不同,也就是说,一个函数可能有多个名字:

function sum(num1, num2) {
    return num1 + num2;
}
alert(sum(1,2));    // 3

var anotherSum = sum;
alert(anotherSum(3,4)); // 7

sum = null;
alert(anotherSum(4, 5));    // 9

需要注意的是sum = null将sum变量与函数取消了关系,但是仍然可以正常调用anotherSum()。

没有重载

JavaScript中并没有类似于java语言的重载机制。

function addNum(num) {
    return num + 1;
}

function addNum(num) {
    return num + 2;
}

var result = add(0);    // 2

上面的例子声明了两个函数,而结果显示后面的函数覆盖了前面的函数。上面的代码等价于:

function addNum(num) {
    return num + 1;
}

function addNum(num) {
    return num + 2;
}

var result = add(0);    // 2

函数声明与函数表达式

JavaScript解析器在向执行环境中加载数据时,会率先读取函数声明,并使其在执行任何代码之前可用;至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

alert(sum(1, 2));
function sum(num1, num2) {
    return num1 + num2;
}

上面的代码可以正常执行。这是因为在代码执行之前,解析器就已经通过名为函数声明提升的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎也能把函数声明提升到顶部。

如果把函数声明改为函数表达式的形式,就会在执行期间导致错误。

alert(sum(1, 2));
var sum = function(num1, num2) {
    return num1 + num2;
};

以上代码会运行错误。因为函数位于初始化语句中,在执行到函数所在的语句之前,变量sum中不保存对函数的引用。

作为值的函数

在JavaScript中的函数本身就是变量,所以函数也可以作为值来使用。这就是说,可以把函数当作一个参数传递给另一个变量。

function sum(add1, arg) {
    return add1(arg);
}

sum函数接收两个参数。第一个是参数是一个函数,第二个参数应该是要传递给该函数的一个值。

// add1执行加1操作
function add1(num) {
    return num + 1;
}

var result = sum(add1, 2);
alert(result);  // 3

function sayHello(name) {
    return "hello, " + name;
}
var result1 = sum(sayHello, "world");
alert(result1);     // "hello, world"

注意:这里sum()函数是通用的,无论第一个参数传进来的是什么函数,都返回这个函数的结果。sum(add1, 2);和sum(sayHello, "world");中传递的都是add1()方法和sayHell0()方法,而不是执行它们返回的结果。

可以从一个函数中返回另一个函数。例如前面提到的数组的sort()方法的比较函数,需要传入两个参数。

function createComparisionFunction(propertyName) {
    return function(obj1, obj2) {
        var value1 = obj1[propertyName];
        var value2 = obj2[propertyName];

        if (value1 < value2) {
            return -1;
        } else if (value1 > value2) {
            return 1;
        } else {
            return 0;
        }
    };
}

上面定义了一个函数,这个函数中嵌套了一个函数,内部函数接收到propertyName参数后,会使用方括号表示法来取得给定属性的值,然后根据值来定义排序规则。

var data = [{name:"zhangsan", age:18}, {name:"lisi", age:19}];
data.sort(createComparisionFunction("name"));
alert(data[0].name);    // lisi

data.sort(createComparisionFunction("age"));
alert(data[0].name);    // zhangsan

函数内部属性

在函数内部,有两个特殊对象:arguments和this。

arguments

arguments是一个类数组对象,包含传入函数中的所有参数。arguments主要用于保存函数参数,除此之外还有一个callee属性,callee是一个指向拥有arguments对象的函数。

下面看一个阶乘的例子:

function factorial(num) {
    if (num <= 1) {
        return 1;
    } else {
        return num * factorial(num - 1);
    }
}

这种定义方法是没有问题的,缺点在函数的运行与函数名factorial紧密耦合在一起了,为了解决这个问题,可以使用arguments.callee。

function factorial(num) {
    if (num <= 1) {
        return 1;
    } else {
        return num * factorial(num - 1);
    }
}

这样,无论引用函数时是什么名字都不影响函数的正常运行。例如:

var newfactorial = factorial;
factorial = function () {
    return 0;
}
alert(newfactorial(5)); // 120
alert(factorial(5));    // 0

this

this引用的是函数据以执行的环境对象。

window.color = "red";
var obj = {color: "blue"};

function sayColor() {
    alert(this.color);
}

sayColor();     // "red",this指window对象
obj.sayColor = sayColor;
obj.sayColor(); // "blue", this指obj对象

在调用函数之前this的值并不确定,this在运行过程中会指代不同对象。在调用sayColor();时,this引用的是全局对象window,this.color相当于window.color;当把sayColor赋值给obj对象并调用obj.sayColor()时,this引用的是obj对象,因此对this.color即obj.color。

caller

ECMAScript5提供了另一个函数对象的属性:caller。它保存着调用当前函数的函数的引用,如果在全局作用域中调用当前函数,值为null。

function outer() {
    inner();
}

function inner() {
    alert(inner.caller);
}

outer();

上面的代码会显示outer()函数的源码。因为outer()调用了inner(),所以inner.caller就执行outer()。

函数属性和方法

前面已经说过,在JavaScript中函数时对象,因此函数也有属性和方法。每个函数。每个函数都包含两个属性:length和prototype。

length属性保存的是调用数组时的参数个数,而不是声明时定义的参数个数。对于JavaScript中的引用类型而言,prototype是保存它们所有实例方法的真正所在。诸如toString()和valueOf()等方法实际上都保存在prototype名下,只不过是通过各自对象的实例访问。在ECMAScript5中,prototype属性是不可枚举的,因此,使用for-in无法发现。

每个函数都包含两个非继承而来的方法:apply()call()。这两个方法都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

apply()方法

apply()方法接收两个参数:第一个参数是在其中运行函数的作用域;另一个是参数数组,它可以是Array的实例,也可以是arguments对象。

function sum(num1, num2) {
    return num1 + num2;
}

function callSum1(num1, num2) {
    return sum.apply(this, arguments);  // 传入arguments
}

function callSum2(num1, num2) {
    return sum.apply(this, [num1, num2]);   // 传入数组对象
}

alert(callSum1(1, 2));  // 3
alert(callSum2(1, 2));  // 3

call()方法

call()方法与apply()方法的作用相同,它们的区别仅在于接收的参数不同。第一个参数也是this,其余参数都直接传递。

function sum(num1, num2) {
    return num1 + num2;
}

function callSum(num1, num2) {
    return sum.call(this, num1, num2);
}

alert(callSum(1, 2));   // 3

在使用call()方法的情况下,callSum()必须明确传入每一个参数,返回值都一样。

apply()和call()最大的作用在于能够扩充函数赖以运行的作用域。

window.color = "red";
var obj = {color: "blue"};

function sayColor() {
    alert(this.color);
}

sayColor();             // red

sayColor.call(this);    // red
sayColor.call(window);  // red
sayColor.call(obj);     // blue

在上面的例子中,sayColor()方法是定义在全局作用域中的,在全局作用域中this.color会转换为window.color,所以sayColor()的结果为red。而sayColor.call(this)sayColor.call(window)显式地在全局作用域中调用函数,结果必然为热点。当运行sayColor.call(obj)时,函数的运行环境就变成了obj,当执行sayColor()时,this.color会转换为obj.color,因此结果为blue。

bind()方法

bind()方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

window.color = "red";
var obj = {color: "blue"};

function sayColor() {
    alert(this.color);
}

var objSayColor = sayColor.bind(obj);
objSayColor();  // blue

在上面的例子中,sayColor()调用bind()并传入对象。创建了objSayColor()函数。objSayColor()函数的this值为obj,因此,即使在全局作用域下调用objSayColor(),结果也是blue。

时间: 2025-01-02 11:36:05

JavaScript:Function类型的相关文章

【JavaScript】Function类型

JavaScript中,每个函数都是Function类的一个实例. 也就是说每一个定义的函数名都是指向Function类型的一个实例. 函数名中存放的是函数的指针(Function类型实例指针). 可以使用Function的构造函数实现,最后一个参数被视为函数体,如: var sum = new Function("num1","num2","return num1+num2");   //不推荐 1.没有重载 因为函数名中存放的是指针,重新定义

浅析JavaScript之Function类型

JavaScript中的函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上只是指向函数对象的指针,保存函数在堆内存中的地址值. 1.定义函数的三种方式: 1.1.函数声明方式 1 function sum(num1, num2){ 2 return num1 + num2; 3 } 1.2.函数表达式 1 var sum = function(num1, num2){ 2 return num1 + num2; 3

JavaScript之Function类型

以下的学习笔记来自于一本在 JavaScript 领域非常有名的书籍< JavaScript 高级程序设计(第 3 版)>,和 孔浩老师的视频教程(孔老师也是参考这本书,丰富了这本书上的内容).我只是一个知识的搬运工,以期通过搬运知识来加深对知识的理解. 函数是 ECMAScript 中最最有意思的部分,最最重要的部分.最有意思的根源在于:函数是对象. 函数就是一个非常特殊的对象,是一个 Function 类型的实例,其实在内存中存储的操作是通过一个键值对来存储的. 函数的第 1 种定义方式,

JavaScript基础——引用类型(三)Function类型

在ECMAScript中函数实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定.函数通常是使用函数声明语法定义的,如: function sum(num1 , num2){ returnnum1 + num2; } 这与下面使用函数表达式定义函数的方式几乎相差无几: var sum = function(num1 , num2){ returnnum1 + num2; };

转载自chaos_JS 的JavaScript中的Function类型浅析

1. Function类型是js中引用类型之一,每个函数实际上都是Function类型的实例对象,具有自己的属性和方法.正因为函数式对象,所以函数名实际上也是一个指向函数对象的指针. 2. 常用的函数定义方式 1. 函数声明: function sum(a , b ){ return a+b; } 2. 表达式: var sum = function(){ return a+b; }; //注意分号 //两种方式的区别: //解释器会率先读取函数声明,并使其在执行之前可以访问,而使用表达式则必须

JavaScript中的Function类型浅析

1. Function类型是js中引用类型之一,每个函数实际上都是Function类型的实例对象,具有自己的属性和方法.正因为函数式对象,所以函数名实际上也是一个指向函数对象的指针. 2. 常用的函数定义方式 1. 函数声明: function sum(a , b ){ return a+b; } 2. 表达式: var sum = function(){ return a+b; }; //注意分号 //两种方式的区别: //解释器会率先读取函数声明,并使其在执行之前可以访问,而使用表达式则必须

JavaScript中的Function类型

函数实际上是对象,每个函数都是Function类型的实例,定义Function函数的方式如下: 1 //第一种:函数声明 2 function sum(num1,num2){ 3 return num1 + num2; 4 } 5 6 //第二种:函数表达式 7 var sum = function(num1,num2){ 8 return num1 + num2; 9 } 10 11 //第三种:Function构造函数 12 var sum = new Function("num1"

说说javascript变量类型和变量类型检测

javascript是一种弱类型语言,它的典型例子就是即变量在使用的时候可以给它赋值任何类型.那么先来看下javascript都有那些变量类型已经它们的使用方法吧. 先来看看javascript都有那些类型吧: string --- 字符串number --- 数值boolean --- 布尔值undefined --- 未申明的变量 或 申明并未赋值null --- 空object  --- 对象function  --- 函数 这里比较有争议的是 function 类型到底要不要归属到变量类

深入理解 JavaScript Function

1.Function Arguments JavaScript 函数的参数 类型可以是 复杂类型如  Object or Array 和简单类型 String Integer null undefined;当参数是 复杂类型的时候,将会把 复杂类型的 引用传出 函数体内,也就是传入函数内的不是 复杂类型的副本,而是其在内存中的指针.当参数是 简单类型的时候,就会直接传值进入函数体内.look the below demostrated: var obj={name:'joe'}; (functi