详解JavaScript函数_javascript技巧

      函数是一组可以随时随地运行的语句,函数作为ECMAScript的核心是很重要的。函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。也就是函数是定义一次但却可以调用或执行任意多次的一段JavaScript代码。函数有时会有参数,即函数被调用时指定了值的局部变量。函数常常使用这些参数来计算一个返回值,这个值也成为函数调用表达式的值。
一、函数声明
       函数对于任何语言来说都是一个核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方,任何时候调用执行。JS中的函数使用function关键字来声明,后跟一组参数以及函数体。
       函数的基本语法是这样的:

<span style="font-size:18px;">function functionName(arg0, arg1, ... argN) {
 statements
}</span> 

       ECMAScript规定的函数声明方式有三种:
(1)普通函数声明

<span style="font-size:18px;">function box(num1,num2){
 return num1+num2;
}</span>

 (2)使用变量初始化什声明函数

<span style="font-size:18px;">var box=function(num1,num2){
 return num1+num2;
}</span> 

(3)使用Function构造函数声明

复制代码 代码如下:

<span style="font-size:18px;">vax box=new Function('num1','num2','num1+num2');</span> 
 
二、函数的类型及函数的调用
 ECMAScript语法规定了
 (1)无参数的函数:函数的声明的时候没有参数,调用函数的时候直接使用即可。

function box(){
 document.write("我是中国人!");
}
box();//函数调用

运行的结果为:我是中国人!
(2)带参数的函数:函数的声明的时候同时定义了参数变量,参数可以是多个。

function box(name,age) {
 document.write("你的姓名是:"+name+"你的年龄是:"+age);
}
box("张三","24");//函数调用

运行的结果为:你的姓名是:张三
                       你的年龄是:24
(3)带有返回值的函数
       带参数和无参数的函数,都没有定义返回值,而是调用后直接执行的,实际上,任何函数都可以通过return语句跟后面的要返回的值来实现返回值
1)、无参数的函数

function box(){
 return "我是中国人!";
}
document.write(box());

同上面的输出结果:我是中国人!
2)、带参数的函数

function box(name,age){
 return "你的姓名是:"+name+"<br/>"+"你的年龄是:"+age;
}
document.write(box("张三","24"));//函数调用
document.write("<hr/>");
var demo=box("李四","23");//也可以重新赋值新的函数
document.write(demo);

运行的结果为:

 (4)作为值的函数(比较特殊)
首先我们来看一个函数作为常规的变量的例子:

function box(sum,num){
 return sum+num;//这里传递的是函数的返回值和普通的变量一样
}
function sum(num){
 return num+10;
}
var result=box(sum(10),10);
document.write("result="+result);

页面的输出结果为:result=30
下面则传递的是函数,仔细和上面的区分:

function box(sum,num){
 return sum(num);//这里传递的是函数
}
function sum(num){
 return num+10;
}
var result=box(sum,10);
document.write("result="+result);

页面的输出结果为:result=20
三、函数的内部属性
       在函数内部,有两个特殊的对象:arguments对象和this对象。arguments对象是类数组对象,包含着传入函数中的所有参数,主要用途是保存函数参数,主要的属性有length,这个属性是动态的判断函数有多少个参数。但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
 (1)arguments对象的length属性
       JS函数不介意传递进来多少参数,也不会因为参数不统一而错误。实际上,函数体内可以通过arguments对象来
接收传递进来的参数。
       我们先来看一个我们在函数传递参数遇到的问题:函数声明时并不知道要定义多少个参数,在调用函数却出现多
出的或不足的问题。

function box(){
 return arguments[0]+"|"+arguments[1];
}
document.write(box(1,2,3,4,5,6)); 

输出的结果为:1|2。因此输出的显然与我们想要做的不符,那么怎么解决呢?
有了arguments对象的length属性我们就能可以得到参数的数量,避免上面的错误出现。

function box(){
 return arguments.length;
}
document.write(box(1,2,3,4,5,6));

输出:6
       我们还可以利用length属性来智能的判断有多少参数,然后把参数进行合理的应用,比如,实现一个加法运算,将所有传进来的数字累加,而数字的个数又不确定。

function box(){
 var sum=0;
 if(arguments.length==0)
 {
 return sum;
 }
 for(var i=0;i<arguments.length;i++)
 {
 sum=sum+arguments[i];
 }
 return sum;//返回累加结果
}
document.write(box(1,2,3,4,5,6));

       输出:21
(2)arguments对象的callee属性
       还是来说问题:对于递归的问题我们很熟悉了,JS中也不例外

function box(num){
 if(num<=1)
 {
 return 1;
 }
 else
 {
 return num*box(num-1);//递归
 }
}
document.write(box(4));

       输出:24
       对于阶乘函数一般要用到递归算法,所以函数内部一定对调用自身,如果函数名不改变是没有问题的,但一旦改变函数名,内部的自身调用需要逐一修改。为了解决这个问题,可以使用arguments.callee来代替。

function box(num){
 if(num<=1)
 {
 return 1;
 }
 else
 {
 return num*arguments.callee(num-1)//递归
 }
}
document.write(box(4));

       输出:24
(3)this对象
       函数内部另一个特殊的对象时this,其行为与Java和C#中的this大致相似,换句话说,this引用的是函数据以行操作的对象,或者说函数调用语句所处的那个作用域。当在全局作用域中调用函数时,this对象引用的就是window(window是一个对象,是JavaScript中最大的对象,是最外围的对象)。

var color="红色";//这里的color是全局变量,并且这个变量是window的属性
document.write(window.color+"<br/>");
document.write(this.color+"<br/>");
var box={
 color:"蓝色",//这里的color是box下的属性,是局部变量
 sayColor:function(){
 return this.color;//此时的this只能是box中的color
 }
};
document.write(box.sayColor()+"<br/>");//局部的
document.write(this.color);//全局的

       运行的结果为:

四、函数属性和方法
(1)JavaScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length和prototype。其中,length属性表示函数希望接受的命名参数的个数。

function box(num1,num2){
 return num1+num2;
}
document.write(box.length);

输出的结果;2
       对于prototype属性,它是保存所有实例方法的真正所在,也就是原型。这个属性我们先不做过多的介绍。prototype属性下有两个方法:apply()和call(),每个函数都包含这两个非继承而来的方法。这两个方法的用途都在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

function box(num1,num2){
 return num1+num2;
}
function sayBox(num1,num2){
 return box.apply(this,[num1,num2]);//this表示作用域,这里是window,[]表示box所需的参数
}
function sayBox2(num1,num2){
 return box.apply(this,arguments);//arguments对象表示box所需的参数
}
document.write(sayBox(10,10)+"<br/>");
document.write(sayBox2(10,10));

       输出的结果为:20
                                20
(2)call()方法和apply()方法延伸
       call()方法和apply()方法相同,它们的区别仅仅在于接收参数的方式不同。对于call()方法而言,第一个参数作用域,没有变化,变化的只是其余参数都是直接传递给函数的。

function box(num1,num2){
 return num1+num2;
}
function callBox(num1,num2){
 return box.call(this,num1,num2);//区别apply()方法
}
document.write(callBox(10,10));

       输出的结果为:20
       call()方法和apply()方法真正的作用是扩展函数赖以运行的作用域

var color="红色";//全局变量
var box={
 color:"蓝色",//局部变量
};
function sayColor(){
 return this.color;
}
document.write(sayColor()+"<br/>");//作用域在Window
document.write(sayColor.call(this)+"<br/>");//作用域在Window下
document.write(sayColor.call(window)+"<br/>");//作用域在Window下
document.write(sayColor.call(box));//作用域在box下,对象冒充

        输出的结果为:

       使用call()方法或者apply()方法来扩充作用域的最大好处就是对象不需要与方法发生任何耦合关系。也就是说,box对象和sayColor()方法之间不会有多余的关联操作,比如;box.sayColor=sayColor;
五、ECMAScript闭包
       ECMAScrip最易让人误解的一点是,它支持闭包。闭包,指的是词法表示包括不被计算的变量的函数,就是说,函数可以使用函数之外定义的变量。
       其实我在前面的博文已经使用到了闭包,比如在轻松学习JavaScript七:JavaScript的流程控制语句中使用的变量time就是全局变量,函数myFunction()使用这个全局变量,并不是函数本身定义的。还是看一下那个实例吧:

var time=new Date().getHours();
document.write("当前北京时间:"+time);
function myFunction()
{
 var x="";
 if (time<20)
 {
 x="Good day";
 }
 document.getElementById("demo").innerHTML=x;
}

(1)简单的闭包实例
       在ECMAScript中使用全局变量是一个简单的闭包实例。请思考下面这段代码输出的结果是什么:

var sMessage = "hello world";
function sayHelloWorld() {
 document.write(sMessage);
}
sayHelloWorld();

       在上面这段代码中,脚本被载入内存后,并没有为函数sayHelloWorld()计算变量sMessage的值。该数捕 sMessage的值只是为了以后的使用,也就是说,解释程序知道在调用该函数时要检查sMessage的值。sMessage将在函数调用sayHelloWorld()是在(最后一行)被赋值,显示消息"hello world"。
(2)复杂的闭包实例
       在一个函数中定义另一个会使闭包变得更加复杂。例如:

var iBaseNum = 10;//全局变量
function addNum(iNum1, iNum2) {
 function doAdd() {
 return iNum1 + iNum2 + iBaseNum;
 }
 return doAdd();
}
document.write(addNum(10,10));

       这里,函数addNum()包括函数doAdd()(闭包)。内部函数是一个闭包,因为它将获取外部函数的参iNum1和iNum2以及全局变量iBaseNum的值。 addNum()的最后一步调用了doAdd(),把两个参数和全局变量相加,并返回它们的和。这里要掌握的重要概念是,doAdd()函数根本不接受参数,它使用的值是从执行环境中获取的,因此输出的结果为:30。
        可以看到,闭包是 ECMAScript 中非常强大多用的一部分,可用于执行复杂的计算。就像使用任何高级函数一样,使用闭包要小心,因为它们可能会变得非常复杂。

以上就是本文的全部内容,希望对大家的学习有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索javascript
函数
javascript函数详解、javascript闭包详解、javascript详解、javascript 继承详解、javascript bind详解,以便于您获取更多的相关知识。

时间: 2024-11-05 11:43:55

详解JavaScript函数_javascript技巧的相关文章

详解javascript函数的参数_javascript技巧

javascript函数可以用任意多个参数来调用,而不用管函数定义时指定了几个参数.因为函数是弱类型的,没有方法去声明它所期望的参数类型,并且给任何函数传递任何类型的值都是合法的. 1.Js函数可以传入不同的参数,如 function writeNString(strMsg){ document.write(strMsg + "<br>"); } 2.Js函数返回值,js函数可以将运行的结果返回,函数可以视为一个黑盒子,使用参数输入数据后产生所需的运行结果,如 functi

详解JavaScript函数对象_javascript技巧

函数 函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块. function One(leve , leve){ //code return leve+leve } 注释: 形参不需要加上类型: return语句为可选,没有return语句的函数返回undefined: 局部变量与全局变量 在函数内声明:局部变量 在函数外声明:全局变量 向一个新变量名赋值时并没有使用var:这个变量会变为新的全局变量 函数可以作为值 形式1: function init(){ alert("One&qu

JavaScript 继承详解 第一篇_javascript技巧

面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++.C#.Java)的开发经验. 在传统面向对象的语言中,有两个非常重要的概念 - 类和实例. 类定义了一类事物公共的行为和方法:而实例则是类的一个具体实现. 我们还知道,面向对象编程有三个重要的概念 - 封装.继承和多态. 但是在JavaScript的世界中,所有的这一切特性似乎都不存在. 因为JavaScript本身不是面向对象的语言,而是基于对象的语言. 这里面就有一些有趣的特性,比如JavaScript中所有事物都是对象, 包

JavaScript 深层克隆对象详解及实例_javascript技巧

 JavaScript 深层克隆对象 今天做项目,有个需求需要用到深层克隆对象,并且要求在原型链上编程 于是心血来潮索性来复习一下这个知识点,在网上找了相应的知识, 克隆对象,这名词看着高大上,其实也没什么,便是拷贝一个长的一模一样的对象 也许有初学的小伙伴在想,那还不简单么,so easy var obj1 = {name: 'payen'}; var obj2 = obj1; 这可并不是克隆对象,obj1和obj2根本就是同一个对象, 他俩指向同一个内存地址空间,拿到了同样的一个小房子 这是

Javascript中call,apply,bind方法的详解与总结_javascript技巧

以下内容会分为如下小节: 1.call/apply/bind方法的来源 2.Function.prototype.call() 3.Function.prototype.apply() 3.1:找出数组中的最大数 3.2:将数组的空元素变为undefined 3.3:转换类似数组的对象 4.Function.prototype.bind() 5.绑定回调函数的对象 6.call,apply,bind方法的联系和区别 1.call/apply/bind方法的来源 首先,在使用call,apply,

微信公众平台开发教程(五)详解自定义菜单_javascript技巧

一.概述: 如果只有输入框,可能太简单,感觉像命令行.自定义菜单,给我们提供了很大的灵活性,更符合用户的操作习惯.在一个小小的微信对话页面,可以实现更多的功能.菜单直观明了,不仅能提供事件响应,还支持URL跳转,如果需要的功能比较复杂,我们大可以使用URL跳转,跳转至我们的网页即可. 注意:自定义菜单,只有服务号才有此功能 接着我们详细介绍,如何实现自定义菜单? 二.详细步骤: 1.首先获取access_token access_token是公众号的全局唯一票据,公众号调用各接口时都需使用acc

详解Bootstrap按钮_javascript技巧

描述 Bootstrap Button(按钮)JavaScript 插件允许您加强按钮的功能.您可以控制按钮的状态,也可以为组件创建按钮组,比如工具条. 什么是必需的 您必须引用 jquery.js 和 bootstrap-button.js - 这两个 JavaScript 文件.它们都位于 docs/assets/js 文件夹内. 如何使用它 您可以不编写任何 JavaScript 只通过标记使用该插件,也可以通过 JavaScript 启用按钮. Bootstrap 提供了一些选项来定义按

详解Bootstrap插件_javascript技巧

在前面 布局组件 章节中所讨论到的组件仅仅是个开始.Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以给站点添加更多的互动.即使您不是一名高级的 JavaScript 开发人员,您也可以着手学习 Bootstrap 的 JavaScript 插件.利用 Bootstrap 数据 API(Bootstrap Data API),大部分的插件可以在不编写任何代码的情况被触发. 站点引用 Bootstrap 插件的方式有两种: 单独引用:使用 Bootstrap 的个别的 *.j

vue.js入门(3)——详解组件通信_javascript技巧

本文介绍vue.js组件,具体如下: 5.2 组件通信 尽管子组件可以用this.$parent访问它的父组件及其父链上任意的实例,不过子组件应当避免直接依赖父组件的数据,尽量显式地使用 props 传递数据.另外,在子组件中修改父组件的状态是非常糟糕的做法,因为: 1.这让父组件与子组件紧密地耦合: 2.只看父组件,很难理解父组件的状态.因为它可能被任意子组件修改!理想情况下,只有组件自己能修改它的状态. 每个Vue实例都是一个事件触发器: $on()--监听事件. $emit()--把事件沿