JavaScript function 类型的使用说明

soゝso 2016-08-22 18:25:16 690
分享到:

Function 类型

每个函数都是Function 类型的实例。函数名实际上就是一个指向函数对象的指针,不会与某个函数绑定。

函数声明方式创建Function,语法如下:

function sum(x,y){
    return x + y;
}

函数表达式定义Function,用var 如下:

var sum = function(x,y){
    return x + y;
};

第二种方法不要忘记在结尾加上分号

另外还可以使用Function 构造函数。如:

var sum = new function("x","y","return x + y");

非常不推荐使用这种形式。

如何证明函数名仅仅是指向函数的指针呢:

var sum = function(x,y){
    return x + y;
};
console.log(sum(1,2)); //3

var anotherSum = sum;
console.log(anotherSum(1,1)); //2

sum = null;
console.log(anotherSum(10,10)); //20

没有重载

同名的后面的函数将会覆盖前面的函数。如:


function add(num){
    return num + 100;
}
function add(num){
    return num + 200;
}
console.log(add(100)); //300

用另外一种写法就可以很清楚的看出原因。如:

var add = function(num){
    return num + 100;
}
add = function(num){
    return num + 200;
}
console.log(add(100)); //300

函数的声明与函数表达式(以及函数声明提升)

解析器会率先读取函数声明,并使其在执行任何代码之前可用(可访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。如:

console.log(sum(1,1)); //2
function sum(x,y){
    return x + y;
}

以上代码可行,是因为在代码开始值钱,解析器就已经通过一个名为函数声明提升(function declaration hoisting)的过程,读取并将函数声明添加到执行环境中去。即使声明函数的代码在调用它的代码后面,JavaScript 引擎也能把函数声明提升到顶部。

但是,如果把函数声明改成函数表达式,则会导致错误。如:

console.log(sum(1,1)); 
var sum = function(x,y){
    return x + y;
}; //TypeError: undefined is not a function (evaluating 'sum(1,1)')

失败的原因就在于函数位于初始化语句中,而不是一个函数声明。

也可同时使用函数声明和函数表达式,但在safari 浏览器中会出错。

作为值的函数

函数也可以作为值来使用,也就是可以将一个函数作为另一个函数的结果返回。如

function callFunction(someFunction,someArgument){
    console.log(someFunction(someArgument));
}
function addNum(x){
    return x + 100;
}
callFunction(addNum,100); //200

要访问函数的指针而不执行函数的话,必须去掉函数名后面的括号。

function compare(func,x,y){
    var num1 = func(x);
    var num2 = func(y);
    var array = [num1,num2];
    
    var result = array.sort(sortFunc);
    console.log(result.toString());
    document.write(result.join(" then "));
    
    
    function sortFunc(value1,value2){
        if (value1 > value2){
            return 1;
        }else if(value2 > value1){
            return -1;
        }else{
            return 0;
        }
    }
}

function add10(num){
        return num + 10;
    }

compare(add10,10000,999100); //10010 then 999110

函数内部属性

这里主要说一下callee属性、this属性以及caller属性。

callee属性的功能就是消除函数名的耦合问题。如:

function min(num){
    if(num == 1){
        return 1;
    }else if(num < 1){
        return 0;
    }else{
        return min(num - 1);
    }
}

var result = min(100);
document.write(result);

上面这个min()函数如果改了函数名,函数里面也相应的需要修改函数名。但添加了callee属性,就不需要修改。如:

function mins(num){
    if(num == 1){
        return 1;
    }else if(num < 1){
        return 0;
    }else{
        return arguments.callee(num - 1);
    }
}

var result = mins(100);
document.write(result);

着就解决了耦合现象所带来的问题。

this这个特殊对象的作用与Java 和C# 中的this 类似。this引用的是函数据以执行的环境对象——或者this值。如:

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

function show(){
    document.write(this.color);
}

show(); //red

obj.show = show;
obj.show(); //yellow

caller用来调用当前函数的函数的引用(源代码)。如:

function sum(x,y){
    plus(x,y);
}

function plus(x,y){
    console.log(x + y);
    document.write("<pre>" + plus.caller + "</pre>");
}

sum(10,20);

如:


(
    function a(){
        document.write("function a");
        b();
        function b(){
            document.write("function b");
            alert(arguments.callee.caller);
        }
    }
)()

用arguments.callee 可能在某些浏览器中会导致错误:

function sum(x,y){
    plus(x,y);
}

function plus(x,y){
    console.log(x + y);
    document.write("<pre>" + arguments.callee.caller + "</pre>");
}

sum(10,20);

函数属性和方法

每个函数都包含两个属性lengthprototype

length属性中,将返回参数的个数。如:

function colors(color1,color2){
    var array = [color1,color2];
    document.write(array.join("/"))
}
colors("red","blue");
document.write(" " + colors.length + "个参数"); //red/blue 2个参数

又如:

function toStr(){
        var result = "";
        for (var i = 0; i < arguments.length; i ++){
            result += arguments[i].toString() + " ";
        }
        document.write(result);
        document.write(" " + arguments.length + "个参数" + "<br/>");
        document.write(" " + arguments.callee.length + "个函数期望参数");
}
toStr(321,32,43243,432,3213);
    
/*
321 32 43243 432 3213 5个参数
0个函数期望参数    
*/

prototype属性。这个属性是保存它们所有实例方法的真正所在。在创建自定义引用类型以及实现继承时,这个属性是非常重要的(以后再单独讨论)。另外,在ECMAScript 5 中,这个属性不可枚举(不能用for-in)。主要的两个非继承方法有apply()call();这两个方法的用途都是在特定的作用域中调用函数。

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

function sum(x,y){
    document.write(x.toString() + y.toString());
}

function plus(){
    return sum.apply(this,arguments);
}

plus(321,"fff");

下面这个则是Array 的实例:

function sum(x,y){
    document.write(x.toString() + y.toString());
}

function plus(a,b){
    return sum.apply(this,[a,b]);
}

plus(321,"fff"); 

call()方法与前者的作用相同,区别在于接收参数的方式不同。第二个参数必须一个个列举出来。如下:

function sum(x,y){
    document.write(x.toString() + y.toString());
}

function plus(a,b){
    return sum.call(this,a,b);
}

plus(321,"fff");

上面例子中plus(a,b) 不能写成plus();call(this,a,b)不能写成call(this,arguments)call(this,[a,b])

高能!!!

高能!!!

事实上,apply()call()真正有价值的用途是扩充函数的作用域。如:

var child = {
    name: "Oliver",
    age: 18
}
var adult = {
    name: "Troy",
    age: 24
}

function showName(){
    document.write(this.name);
}

showName.call(adult); //Troy
showName.call(child); //Oliver

使用上面这两个方法来扩充作用域的最大好处就是对象不需要与方法又任何耦合关系。

ECMAScript 5 还定义了一个方法:bind()。this 的值会被绑定到传给bind()函数的值。如:

var child = {
    name: "Oliver",
    age: 18
}
var adult = {
    name: "Troy",
    age: 24
}

function showName(){
    document.write(this.name);
}

var newFunc = showName.bind(child);
newFunc(); //Oliver
关于作者
目前就职于国内某电商平台公司打杂。。
相关文章
Javascript模块化编程,本站使用 require.js 优化JS加载, require.js下载
Elasticsearch Date类型,时间存储相关说明
Javascript 生成UUID,Java生成UUID
怎么合理管理、提高Javascript的性能
JS中 “is not defined” 如何判断defined,defined和undefined 的区别
JSON.stringify 函数 (JavaScript)讲解
js html5 canvas制作多个小球碰撞的动画效果
一些Node.js开发工具、开发包、框架等总结
详解JavaScript中splice()方法,有Demo详细介绍
Javascript 删除节点后是否需要将手动将事件解绑?
最新文章
免费天气API,全国天气 JSON API接口,可以获取五天的天气预报 39153
SOJSON 使用又拍云 CDN 整体架构,解决百度 SEO 方案 33
又拍云(Upyun)刷新CDN,云存储缓存 —JavaAPI 20
JS解密,JavaScript 解密,任何JS加密都能100%解密,以及JS 加密讲解 83
阿里云DNS 解析讲解,SEO配置搜索引擎线路解析 45
百度秒收录教程,怎么做到百度秒收入你的页面,SEO 教程 101
CDN 请求返回 connection reset by peer,被拦截请求解决方案 37
Google AdSense 申请技巧,谷歌广告申请通不过教程 69
Mac 安装 JMeter,JMeter 下载,JMeter Http 压力测试【图解】 51
支付宝吱口令自动复制脚本,自动复制 JavaScript 代码介绍 916
最热文章
免费天气API,全国天气 JSON API接口,可以获取五天的天气预报 39097
Elasticsearch教程(四) elasticsearch head 插件安装和使用 109124
Elasticsearch教程(六) elasticsearch Client创建 73308
Elasticsearch教程(八) elasticsearch delete 删除数据(Java) 70761
Elasticsearch教程(二),IK分词器安装 67505
Elasticsearch教程(三),IK分词器安装 (极速版) 54092
Elasticsearch教程(五) elasticsearch Mapping的创建 51628
Elasticsearch教程(一),全程直播(小白级别) 51390
Elasticsearch教程(七) elasticsearch Insert 插入数据(Java) 47779
Elasticsearch权威指南-中文.pdf,Elasticsearch 中文文档下载 40948

骚码加入我们 / 千人QQ群:259217951

入群需要5元,如果没有QQ钱包,可以先Alipay、微信,赞助然后加群主拉进。

二维码生成 来自 >> 二维码生成器

支付扫码

所有赞助/开支都讲公开明细,用于网站维护:赞助名单查看

正在加载... ...