函数(function语句、Function构造函数、函数直接量)

 

 

函数(function语句、Function构造函数、函数直接量) 

函数定义

函数是由这样的方式进行声明的:关键字 function、函数名、一组参数,以及置于括号中的待执行代码。

函数的构造语法有这三种:

 

function functionName(arg0, arg1, ... argN) { statements }//function语句   
var function_name = new Function(arg1, arg2, ..., argN, function_body);//Function()构造函数    
var func = function(arg0, arg1, ... argN) { statements };//函数直接量  
 

 示例:

 

function f(x){return x*x};//function语句    
var f = new Function("x","return x*x;");//Function()构造函数    
var f = function(x){return x*x;};//函数直接量   
 

 如果函数无明确的返回值,或调用了没有参数的 return 语句,那么它真正返回的值是 undefined。   

重载?

ECMAScript中的函数不能重载 。可用相同的名字在同一个作用域中定义两个函数,而不会引发错误,但真正使用的是后一个函数。考虑下面的例子:

 

function doAdd(iNum) {   
    Alert(iNum + 100);   
}   
function doAdd(iNum) {   
    Alert(iNum + 10);   
}   
doAdd(10);//20   
 
 

  不过可以使用arguments对象避开这种限制。

Function()构造函数

函数实际上是功能完整的对象 。Function类可以表示开发者定义的任何函数。用Function类直接创建函数的语法如下:

Js代码

var function_name = new function(arg1, arg2, ..., argN, function_body)    

 在上面的形式中,每个 arg 都是一个参数,最后一个参数是函数主体(要执行的代码)。这些参数必须是字符串。

 

var sayHi = new Function("sName", "sMessage", "alert('Hello ' + sName + sMessage);");   
sayHi("jzj,", "你好!");//Hello jzj,你好!    
 
 

  函数名只是指向函数的变量,那么可以把函数作为参数传递给另一个函数吗?答案是可以的,请看:

 

function callAnotherFunc(fnFunction, vArgument) {   
 fnFunction(vArgument);   
}   
var doAdd = new Function("iNum", "alert(iNum + 10)");   
callAnotherFunc(doAdd, 10); //输出 "20"   
 

注意:尽管可以使用 Function 构造函数创建函数,但最好不要使用它,因为用它定义函数比用传统方式要慢得多。不过,所有函数都应看作 Function 类的实例 。

 

如果你定义的函数没有参数,那么可以只需给构造函数传递一个字符串(即函数的主体)即可。

 

注意:传递给构造函数Function()的参数中没有一个用于说明它要创建的函数名。用Function()构造函数创建的未命名函数有时被称为“匿名函数”。

 

Function()函数允许我们动态地建立和编译一个函数,它不会将我们限制在function语句预编译的函数体中。

函数直接量

函数直接量是一个表达式,它可以定义匿名函数。函数直接量的语法和function语句非常相似,只不过它被用作表达式,而不是用作语句,而且也无需指定函数名。语法:

Js代码

var func = function(arg0, arg1, ... argN) { statements };//函数直接量  

虽然函数直接量创建的是未命名函数,但是它的语法也规定它可以指定函数名,这在编写调用自身的递归函数时非常有用,例如:

 

var f = function fact(x) {   
    if (x <= 1) {   
        return 1;   
    } else {   
        return x * fact(x - 1);   
    }   
};  
 

注:它并没有真正创建一个名为fact()函数,只是允许函数体用这个名字来引用自身。JavaScript1.5之前的版本中没有正确实现这种命名的函数直接量。

函数引用

函数名并没有什么实质意义,它不过是用来保存函数的变量名字,可以将这个函数赋给其他变量,它仍然会以相同方式起作用:

 

function square(x){return x*x;}   
var a = square;   
var b = a(5);//b 为25   
 

 这有点像C++中的函数指针了。

Function()构造函数和函数直接量差别

Function()构造函数和函数直接量之间的差别有一点就是:使用构造函数Function()创建的函数不使用词法作用域,相反的,它们总是被顶级函数来编译,如:

 

var y = "global";   
function constructFunction() {   
    var y = "local";   
    //Function()构造函数   
    return new Function("return y;");//不使用局部作用域   
}   
function constFunction() {   
    var y = "local";   
    //函数直接量   
    var f = function () {   
        return y;//使用局部作用域   
    };   
    return f;   
}   
//显示 global,因为Function()构造函数返回的函数并不使用局部作用域   
alert(constructFunction()());   
//显示 global,因为函数直接量返回的函数并使用局部作用域   
alert(constFunction()());  
 

函数的实际参数:Arguments对象 

在函数代码中,使用特殊对象arguments ,标识符arguments引用Arguments对象。开发者无需明确指出参数名,就能访问它们。例如,在函数sayHi()中,第一个参数是message。用arguments[0]也可以访问这个值,即第一个参数的值(第一个参数位于位置0,第二个参数位于位置1,依此类推)。因此,无需明确命名参数,就可以重写函数:

 

function sayHi() {   
    if (arguments[0] == "bye") {   
        return;   
    }   
    Alert("Hello" + arguments[0]);   
}  
 

当函数具有命名的参数时,Arguments对象的数组元素是存放函数参数的局部问题的同义词。arguments[]数组和命名了参数不过是引用同一变量的两种不同方法。用参数名改变一个参数的值同时会改变通过arguments[]获得的值,当然通过arguments[]数组改变参数的值同样会改变用参数名获取的参数值。如:

 

 
function f(x) {   
    alert(x);//显示参数的初始值    
    arguments[0] = null;//改变数组元素也会改变x    
    alert(x);//现在显示 null    
}  
 

Arguments的属性length

arguments还具有length属性,参数的个数可用arguments.length 得到。

与其他程序设计语言不同,ECMAScript不会验证传递给函数的参数个数是否等于函数定义的参数个数。开发者定义的函数都可以接受任意个数的参数(根据Netscape的文档,最多能接受25个),而不会引发任何错误。任何遗漏的参数都会以undefined传递给函数,多余25的参数将忽略。 用arguments对象判断传递给函数的参数个数,即可模拟函数重载:

 

 

function doAdd(iNum) {   
    Alert(iNum + 100);   
}   
function doAdd(iNum) {   
    Alert(iNum + 10);   
}   
doAdd(10);//20   
 

  虽然不如重载那么好,不过已足可避开ECMAScript的这种限制。

Arguments的属性callee

Arguments对象还定义了callee属性,用来引用当前正在执行的函数。这对象未命名的函数调用自身非常有用。下面是一个未命名的函数直接量,用于计算阶乘:

 var f = function (x) {   

    if (x <= 1) {   
        return 1;   
    }   
    return x * arguments.callee(x - 1);   
};   
alert(f(3));//6  

 

 

当然也可以给它临时取个名:

var f = function tmpName(x) { if (x <= 1) { return 1; } return x * tmpName(x - 1); }; alert(f(3));//6

函数的属性length

因为函数是引用类型,所以它们也有属性和方法。  ECMAScript  定义的函数的属性  length (只读) 声明了函数声明的参数个数,与arguments.length不同,这个length属性在函数体的内部与外部都有效 。例如:  

 

 

function doAdd(iNum) {   
    alert(iNum + 10);   
}   
function sayHi() {   
    alert("Hi");   
}   
alert(doAdd.length);//输出: 1    
alert(sayHi.length);//输出: 0  
 

 

无论定义了几个参数, ECMAScript 函数可以接受任意多个参数(最多 25 个)。属性 length 只是为查看默认情况下函数声明的参数个数提供了一种简便的方式,它不你见arguments是动态变的。

 

函数的属性prototype

每个函数都有一个prototye属性,它引用的是预定义的原型对象。原型对象在使用new运算符把函数作为构造函数时起作用,它在定义新对象类时起着非常重要的的作用。

...

 

定义你自己的函数属性

当函数需要使用一个在调用过程中都保持不变的值时,使用Function对象的属性比定义全局变量(这样会使用名字空间变得散乱)更加方便。虽然我们可以将这信息存储在一个全局变量中,但是由于这一信息是由函数自己使用的,所以不必使用全局变量,最好的方法莫过于将信息存储在Function对象的属性中。

 

//创建并初始化静态变量   
//因为函数声明在执行代码前处理,所以在函数声明前这样赋值是可以的   
uniqueInteger.counter = 0;   
  
//下面的函数每次被调用时返回值都不同,   
//而且使用它自己的静态属性来跟踪它上次返回的值   
function uniqueInteger() {   
    //给静态变量加1,然后返回它的值   
    return uniqueInteger.counter++;   
}   
  
alert(uniqueInteger());//0   
alert(uniqueInteger());//1  
 
 

函数的方法apply()和call()

这2个关键字可以很简单地理解为 进行this引用对象(运行空间)强制转换 , 二者的语法如下:

fun.call(object, arg1, arg2, ...)

fun.apply(object, [arg1, arg2, ...])

二者目的是相同的(动态更改函数的运行空间, 或者称作更改this指向的对象),只是在提供给函数的参数上的调用方法不同。

 

使用这两个方法可以像调用其他对象的方法一样调用函数。call()和applay()的第一个参数都是要调用的函数的对象,在函数体内这一参数是关键字this的值(意思是会把第一个参数赋给函数体内的this,this以后就指向了第一个参数)。call()的剩余参数是传递给要调用的函数的值。例如,要把两个数字传递给函数f(),并将它作为对象o的方法调用,可以使用如下的代码:

 

function f (arg1, arg2){   
    this.attr1 = arg1;   
    this.attr2 = arg2;   
}   
//-----第一种调用法   
//如果在调用时前面未明确指定对象,则默认为window对象   
f(1,2);   
//我们可以看到上面确实是由window对象来调用的   
alert(window.attr1);   
alert(window.attr2);   
  
//-----第二种调用法   
//此时构造体内的this就是当前new出来的对象   
var fun = new f(3,4);   
alert(fun.attr1);//3   
alert(fun.attr2);//4   
  
//-----第三种调用法   
var o = {};   
//此时构造函数体内的this就指向了o   
f.call(o,5,6);   
alert(o.attr1);//5   
alert(o.attr2);//6   
//f.call(o,5,6);与下面的代码相似   
o.m = f;   
o.m(5,6);   
delete o.m;   
alert(o.attr1);//5   
alert(o.attr2);//6   
  
//虽然前面指定了调用对象,但this还是指向o   
window.f.call(o,7,8);   
alert(o.attr1);//7   
alert(o.attr2);//8  
 apply()方法和call()方法相似,只不过要传递给函数的参数是数组指定的:
Js代码
f.apply(o,[5,6]);  
 
 

 例如,要找到一个数字数组中的最大数字,可以用apply()方法把数组元素传递给Math.max()函数:

Js代码

var array_of_numbers = [5,7,3,6];   

var biggest = Math.max.apply(null, array_of_numbers);   

alert(biggest);//7  

函数的方法valueOf()和toString() 

Function  对象也有与所有对象共享的标准  valueOf ()  方法和  toString ()  方法。这两个方法返回的都是函数的源代码,在调试时尤其有用:

 

function doAdd(iNum) {   
    alert(iNum + 10);   
}   
alert(doAdd.toString());   
alert(doAdd.valueOf());
 

 

 

Javascript中创建对象的语法是在new运算符的后面跟着一个函数的调用。如 

 

复制代码 代码如下:

 

var obj = new Object(); 

var date = new Date(); 

 

运算符new首先创建一个新的没有任何属性的对象,然后调用该函数,把新的对象作为this关键字的值传递。 

复制代码 代码如下:

 

var date = new Date()的伪代码的实现就是 

var obj = {}; 

var date = Date.call(obj); 

 

构造函数的作用就是初始化一个新创建的对象,并在使用对象前设置对象的属性。如果定义自己的构造函数,只需要编写一个为this添加属性的函数就可以了。下面的代码定义了一个构造函数: 

复制代码 代码如下:

 

function Rectangle(w, h) 

this.width = w; 

this.height = h; 

 

然后,可以使用new运算符调用这个函数来创建对象的实例 

复制代码 代码如下:

 

var rect = new Rectange(4,8); 

 

构造函数的返回值 

Javascript中的构造函数通常没有返回值。但是,函数是允许有返回值的。如果一个构造函数有一个返回值,则返回的对象成为new表达式的值。在此情况下,作为this的对象将会被抛弃。 

使用构造函数定义法 

语法 

复制代码 代码如下:

 

var object=new objectname(); 

var -- 声明对象变量 

object -- 对象的名称 

new -- new的关键词(JavaScript关键词) 

objectname -- 构造函数名称 

 

示例 

复制代码 代码如下:

 

//定义构造函数 

function Site(url, name) 

this.url = "www.jb51.net"; 

this.name ="梦之都"; 

//使用构造函数产生一个JavaScript对象的实例 

var mysite = new Site(); 

alert(mysite.url); 

 

构造函数通常可以初始化对象中的一些内容,JavaScript内部提供的一些对象通常需要使用构造函数的方法生成。JavaScript函数的内容将在下一章介绍。 

直接定义法创建JavaScript对象 

复制代码 代码如下:

 

//定义对象语法 

var object={}; 

//对象内的属性语法(属性名(property)与属性值(value)是成对出现的) 

object.property=value; 

//对象内的函数语法(函数名(func)与函数内容是成对出现的) 

object.func=function(){...;}; 

 

var -- 声明对象变量 

object -- 对象的名称 

property -- 对象的属性名 

func -- 对象的方法名 

说明:对象可以包含一些属性(函数可以看作带有括号的特殊属性),每个属性有名称和值。名称可以是任何字符串甚至是空。值可以是任何javascript类型,但不能是undefined。 

使用定义法定义的对象示例 

复制代码 代码如下:

 

var site = {}; 
site.URL = "www.jb51.net"; 
site.name = "脚本之家"; 
site.englishname = "jb51"; 
site.author = "脚本"; 
site.summary = "免费的网页设计教程"; 
site.pagescount = 100; 
site.isOK = true; 
site.startdate = new Date(2005, 12); 
site.say = function(){alert(this.englishname+" say : hello world!")}; 
site.age = function(){var theage=(new Date().getFullYear())-site.startdate.getFullYear();alert(this.name+"已经"+theage+"岁了!")} 
 

 

使用构造函数创建JavaScript对象示例 -- 可以尝试编辑 

使用构造函数创建JavaScript对象 

上面的方法定义了一个site的对象,并且为其定义了七个属性,与两个个方法。 

say方法会打印出jb51 say : hello world!的字符串 

age方法会计算出梦之都网站的年龄 

猴子提示: 注意每个属性与函数前面都要加上对象的名称,否则JavaScript无法判断它是属于那个对象的。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值