JS函数总结,整理Javascript函数学习笔记

作者: 网络应用  发布:2019-09-03

1、什么是函数
如果需要多次使用同一段代码,可以把它们封装成一个函数。函数(function)就是一组允许在你的代码里随时调用的语句。每个函数实际上是一个短小的脚本。
如:要完成多组数和的功能。

声明:本文是学习阮一峰的JS标准参考教程,的学习笔记,并不是自己原创。

var sum;
sum = 3+2;
alear(sum);

sum = 7+8;
alear(sum);
......//不停的重复两行代码

1. 函数声明(Function Declaration)

如果要实现8组数的和,就需要16行代码,实现的越多,代码行也就越多。所以我们可以把完成特定功能的代码块放到一个函数里,直接调用这个函数,就省去重复输入大量代码的麻烦。使用函数完成:

函数声明有3种方法

  1. function命令
  1. 函数表达式
  2. Function构造函数

举例:

  1. function命令
function print(s){
    console.log(s);
}
function:命令名
print:函数名,用户自定义
s:参数名,用户自定义
{
    函数体;用户自定义
}
  1. 函数表达式
var print = function(s) {
  console.log(s);
};
//将一个**没有函数名**的函数赋值给了一个变量;
//注意末尾`}`后是有`;`的
  1. Function构造函数
var add = new Function(
  'x',
  'y',
  'return x + y'
);
//最后一个参数是函数体,如果只有一个参数,那么唯一的参数就是函数体。
//这种方法不直观,所以很少用。
// 等同于
function add(x, y) {
  return x + y;
}
function add(a,b){
  sum = a+b;//只需要写一次就可以
 };
 add2(3,2);
 add2(7,8);
 ......//只需要调用函数就可以

函数重复声明

同一个含数被声明了多次,那么后面的函数会覆盖掉前面的函数

2、定义函数
定义函数语法

函数声明的提升

函数和变量一样,都存在声明的提升。
但是有几个需要注意的地方

f();
var f = function (){};
// TypeError: undefined is not a function

这种是采用函数表达式的方式声明函数,并不会得到提升,而会报错,上面代码等同于下面。

var f;
f();
f = function () {};

因此,如果同时采用function命令和赋值语句声明同一个函数,最后总是采用赋值语句的定义。

var f = function() {
  console.log('1');
}

function f() {
  console.log('2');
}

f() // 1
 function 函数名(参数argument){
  函数体statements;
 }
 //function定义函数的关键字,“函数名”你为函数取的名字,“函数体”替换为完成特定功能的代码。


function shout(){
   var beatles = Array("John","Paul","George","Ringo");
   for (var count = 0; count < beatles.length; count++){
     alert(beatles[count]);
   }
 }
 //这个函数里面的循环语句将依次弹出对话框来显示beatles里面内容。 
 shout();调用函数,执行脚本里的动作

2. 函数的调用

函数的调用方法:
函数名(参数1,参数2,参数3……);

function add(x,y){
    return x + y;
}
add(1,2);//3

函数调用后,会返回return 后面的表达式的值,如果函数没有return,默认返回undefined

完成对两个数求和并显示结果的功能:

3. 函数的递归(recursion)

函数调用自己,简称函数递归。
举个栗子:

//函数可以用来计算n的阶乘
function factorial(n){
    if(n===1){      //结束条件
        return 1;
    }else{
        return n*factorial(n-1);
    }
}

factorial(5);//5*4*3*2*1=120

递归需要有自己的结束条件,否则会一直调用下去,无法停止。

<script type="text/javascript">
  function add2(){
    sum = 3+2;
    alert()sum;
   }
   add2();
 </script>

4. 函数的属性

函数有2个重要属性

  1. name属性
  1. length属性

3、函数调用
函数定义好后,是不能自动执行的,需要调用它,直接在需要的位置写函数名。
第一种情况:在<script>标签内调用。

name属性

name属性返回 function命令后的函数名

function f1() {}
f1.name // 'f1'

var f2 = function () {};
f2.name // ''

var f3 = function myName() {};
f3.name // 'myName'(真正的函数名还是f3,myName这个名字只在函数体内部可用)
<script type="text/javascript">
   function add(){
     sum = 1+1;
     alert(sum);
  }
   add();//调用函数,直接写函数名。
</script>

length属性

length属性返回函数预期传入的参数个数,即函数定义之中的参数个数,和调用函数时具体传了几个参数无关。

function f(a, b) {}
f(1,2,3);//和调用时具体穿了几个参数没有关系
f.length // 2

第二种情况:在HTML文件中调用,如通过点击按钮后调用定义好的函数。

5. 函数的方法

<html>
 <head>
 <script type="text/javascript">
   function add2(){
     sum = 5 + 6;
     alert(sum);
   }  
 </script>
 </head>
 <body>
 <form>
  <input type="button" value="click it" onclick="add2()"> //按钮,onclick点击事件,直接写函数名
 </form>
 </body>
 </html>

toString方法

返回函数的源码

function f() {
  a();
  b();
  c();
}

f.toString()

"function f() {
  a();
  b();
  c();
 }"

返回的内容是字符串。
这个方法的一个典型应用是:实现多行字符串的输出

var multiline = function (fn) {
  var arr = fn.toString().split('n');
  return arr.slice(1, arr.length - 1).join('n');
};

function f() {/*
  这是一个
  多行注释
*/}

multiline(f);
// " 这是一个
//   多行注释"

4、有参数的函数
其实,定义函数还可以如下格式:
function 函数名(参数1,参数2){
   函数代码
 }

在定义函数时,你可以为它声明任意多个参数,只要用逗号把它们分隔开来就行。在函数内部,你可以像使用普通变量那样使用它的任何一个参数。
按照这个格式,函数实现任意两个数的和应该写成:

6. 函数作用域

JS中有两种作用域

  1. 全局作用域
  1. 函数作用域
    注:JS中没有区块作用域
function add2(x,y){
   sum = x + y;
   document.write(sum);
 }
 //x和y则是函数的两个参数,调用函数的时候,我们可通过这两个参数把两个实际的加数传递给函数了。

全局变量

在函数外声明的变量属于全局作用域,任何函数内部都可以使用。
注意:在函数中声明变量时如果不加var ,那么声明的依然是一个全局变量。
使用var 声明变量时,只要不是出现在函数体内部,一律是全局变量

实现如下功能: 定义函数实现三个数的和,函数名为add3。
计算5、8、3/7、1、4两组三个数的和。

局部变量

在函数内部声明的变量只在声明它的函数内部有效,属于局部变量。

 <script type="text/JavaScript">
   function add3(x,y,z) {
   sum = x + y +z;
     document.write(x+"、"+y+"、"+z+"和:"+sum+"<br/>");
   }
   add3(5,8,3);
   add3(7,1,4); 
 </script>

变量覆盖

当出现全局变量和局部变量重名的情况时,局部变量会覆盖掉全局变量。

5、返回值的函数
函数不仅能够(以参数的形式)接收数据,还能够返回数据。我们完全可以创建一个函数并让它返回一个值、一个字符串、一个数组或是一个布尔值。这是需要用到return语句。

函数的作用域

函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。

function foo() {
  var x = 1;
  function bar() {
    console.log(x);
  }
  return bar;
}
bar();
//VM630:1 Uncaught ReferenceError: bar is not defined(…)

bar定义在foo内部,在外面使用bar就会报错

 function multiply(num1,num2){
   var total = num1*num2;
   return total;
 }

7. 参数

之前通过"document.write"把结果输出来,现在使用函数输出
我们只要把"document.write(sum)"这行改成如下代码:

参数的省略

函数的参数不是必须的

function f(a,b){
    console.log(a);
    console.log(b);
}
f(1);
//1
//undefined

不管提供几个参数,js都不会报错,被省略的参数会默认使用undefined代替。上面参数省略,相当于下面。

f(1,undefined);
 function add2(x,y){
   sum = x + y;
   return sum; //返回函数值,return后面的值叫做返回值。
 }
 //还可以通过变量存储调用函数的返回值:
 result = add2(3,4);//语句执行后,result变量中的值为7。

为参数设置默认值

function f(a) {
  (a !== undefined && a !== null) ? a = a : a = 1;
  return a;
}

f() // 1
f('') // ""
f(0) // 0

上例中为函数f的a参数设置默认值为1。

例:下面这个函数只有一个参数(一个华氏温度值),它将返回一个数值(同一温度的摄氏温度值):

参数的传递方式

参数的传递方式分两种:

  1. 传值传递
  1. 传址传递

函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)
如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)

 <script type="text/javascript">
   function convertToCelsius (temp) {
     var result = temp - 32;
     result = result / 1.8;
     return result;
   }
   //函数的真正价值体现在,我们还可以把它们当做一种数据类型来使用,这意味着可以把一个函数的调用结果赋给一个变量:
   var temp_fahrenheit = 95;
   var temp_celsius = convertToCelsius(temp_fahrenheit);
   alert(temp_celsius);
 </script>

原始类型变量变为传址传递

某些情况下,如果需要对某个原始类型的变量,获取传址传递的效果,可以将它写成全局对象的属性。

var a = 1;

function f(p) {
  window[p] = 2;
}
f('a');

a // 2

图片 1

8. arguments对象

arguments是对象;
包含函数运行时的所有参数;
该对象只能在函数体内部使用。

var f = function(one) {
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
}
f(1, 2, 3)
// 1
// 2
// 3

上面的例子说明,arguments里面的是函数调用时实际的参数,而不是函数定义时的形参。

可以为参数赋值(严格模式下禁用)

var f = function(a, b) {
  arguments[0] = 3;
  arguments[1] = 2;
  return a + b;
}

f(1, 1)
// 5

在这个例子里,变量temp_celsius的值将是35,这个数值由convertToCelsius函数返回。
在命名变量时,我用下划线来分隔各个单词;在命名函数时,我从第二个单词开始把每个单词的第一个字母写成大写形式(也就是驼峰命名法)。
 1)、变量的作用域
变量既可以是全局的,也可以是局部的。
全局变量(global variable)可以在脚本中的任何位置被引用。一旦你在某个脚本里声明了一个全局变量,就可以从这个脚本中的任何位置------包括函数内部------引用它。全局变量的作用域是整个脚本。
局部变量(local variable)只存在于声明它的那个函数的内部,在那个函数的外部是无法引用它的。局部变量的作用域仅限于某个特定的函数。
可以用var关键字明确地为函数变量设定作用域。
如果在某个函数中使用了var,那个变量就将被视为一个局部变量,它只存在于这个函数的上下文中;反之,如果没有使用var,那个变量就将被视为一个全局变量,如果脚本里已经存在一个与之同名的全局变量,这个函数就会改变那个全局变量值。
例子:

arguments 的length属性

function f() {
  return arguments.length;
}

f(1, 2, 3) // 3
f(1) // 1
f() // 0

注意和函数的length属性区别。

function square(num){
   total = num*num;
   return total;
 }
 var total = 50;
 var number = square(20);
alert(total);

callee属性

该属性可返回对应函数,严格模式禁用,所以不建议使用。可以通过该属性达到调用自身的效果。

var f = function(one) {
  console.log(arguments.callee === f);
}

f() // true

这是错误的,number的值为400,但是这里alert弹出的是total的值,应该是50.

arguments不是数组

因为不是数组,所以不能使用数组的方法,如果要使用,需提前转为数组。具体转换方式如下:

var args = Array.prototype.slice.call(arguments);

// or

var args = [];
for (var i = 0; i < arguments.length; i++) {
  args.push(arguments[i]);
}

这些代码将不可避免地导致全局变量total的值发生变化。

9. 函数闭包

全局变量total的值变成了400.我的本意是让square()函数只把它计算出来的平方值返回给变量number,但因为未把这个函数内部total变量明确地声明为局部变量,这个函数把名字同样是total的那个全局变量的值也改变了。

背景

前面讲过函数内部的变量不可以被外面访问,当有些情况下我们必须要访问函数内部变量时,就可以用闭包来解决

具体方法:在函数内部再创建一个函数,并将该函数作为返回值

function f1() {
  var n = 999;
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 999

闭包就是函数f2,即能够读取其他函数内部变量的函数。

把这个函数写成如下的样子才是正确的:

闭包的特点

闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。请看下面的例子,闭包使得内部变量记住上一次调用时的运算结果。

闭包使诞生的环境一直存在

function createIncrementor(start) {
  return function () {
    return start++;
  };
}

var inc = createIncrementor(5);

inc() // 5
inc() // 6
inc() // 7
 function square(num){
   var total = num*num;
   return total;
 }
 var total = 50;
 var number = square(20);
 alert(total);
 </script>

闭包的弊端

注意,外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。

正确结果:

10. 立即执行函数表达式(Immediately Invoked Function Expression)

有时候我们需要在定义函数之后,立即调用函数,一下两种写法可以满足需求:

(function(){ /* code */ }());
// 或者
(function(){ /* code */ })();

但是下面的写法是错误的

function(){ /* code */ }();
// SyntaxError: Unexpected token (

原因是:function关键字既可以当语句,也可以当表达式。
JS引擎规定,如果function关键字出现在行首,一律解释为语句。JS引擎看到行首是function关键字之后,认为这一段都是函数的定义,不应该是圆括号结尾,所以就报错了。

通常情况下,只对匿名函数使用这种“立即执行的函数表达式”。它的目的有两个:一是不必为函数命名,避免了污染全局变量;二是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。

另外两篇不错的文章:
函数作用域

深入理解javascript中的立即执行函数(function(){…})()

图片 2

以上就是关于Javascript函数的学习笔记,还涉及到了一些变量的知识点,希望对大家的学习有所帮助。

您可能感兴趣的文章:

  • js 正则表达式之test函数讲解
  • js中递归函数的使用介绍
  • JS函数实现动态添加CSS样式表文件
  • js 在定义的时候立即执行的函数表达式(function)写法
  • js split函数用法总结(从入门到精通)
  • JS删除数组元素的函数介绍
  • JavaScript substr() 字符串截取函数使用详解
  • JS中setInterval、setTimeout不能传递带参数的函数的解决方案
  • 详解JavaScript函数

本文由王中王开奖结果发布于网络应用,转载请注明出处:JS函数总结,整理Javascript函数学习笔记

关键词:

上一篇:没有了
下一篇:没有了