Maison  >  Article  >  interface Web  >  Explication détaillée des fonctions en JavaScript

Explication détaillée des fonctions en JavaScript

小云云
小云云original
2018-03-17 15:53:181334parcourir

(1). Qu'est-ce qu'une fonction ?

Un paquet de n instructions avec des fonctions spécifiques. Seules les fonctions sont exécutables, les autres types de données ne sont pas exécutables. Les fonctions sont aussi des objets.

(2). La fonction de la fonction

→ Améliorer la réutilisation du code

→ Facile à lire et communiquer

(3) Définition de la fonction

方式一:函数声明(推荐使用)  function     函数名(参数列表) 
{  //执行代码  }方式二:函数表达式(推荐使用)   var 变量名 = function(参数列表) {(推荐使用)    //执行代码   }
 var 变量名 = function 函数名(参数列表) 
 {  //执行代码    }方式三:构造器(了解)
 function     函数名(参数列表) 
 {  //执行代码  }


<span style="font-size: 14px;">function xiYiJi() {//函数声明<br/>	console.log("您好")<br/>}<br/>var fn = function(){//表达式<br/>	console.log("函数表达式")<br/>};<br/>var fn2 = function show(){//表达式<br/>	console.log(1);<br/>}<br/>var fn3 = new Function("console.log(4)");//构造器<br/>fn3();</span>

Utilisation de la fonction : nom de la fonction (paramètres réels correspondant à la liste des paramètres) ;

Remarque : la ou les listes de paramètres sont facultatives, l'utilisation spécifique dépend des besoins. Si plusieurs fonctions définies portent le même nom, les fonctions les plus récentes écraseront les précédentes.

(4). Comment prouver qu'une fonction est un objet

1.fn instanceof Object=== true
2. . Utiliser des fonctions avec des attributs et des méthodes
Attributs : prototype/__proto__
Méthode : call()/apply()/bing()
3. De nouveaux attributs/méthodes peuvent être ajoutés

<span style="font-size: 14px;">function fn () {}<br/>        console.log(fn instanceof Object=== true)//true<br/>        //3.可以添加新的属性/方法<br/>            fn.a=3;<br/>            console.log(fn.a)</span>


(5). Les fonctions ont 4 rôles

Fonction générale (appel direct), constructeur (appel via new), méthode (appel via objet ), objet (en appelant des propriétés/méthodes internes)

(6).

①test() : Appeler directement

②new test() : Appeler via un nouveau

Remarque : utiliser le mot-clé new consiste à appeler la fonction en tant que constructeur, c'est-à-dire à construire un objet. S'il n'y a pas de réécriture artificielle de la valeur renvoyée lors de l'appel du constructeur, alors l'objet renvoyé est généré par l'analyseur lui-même. Appeler une fonction sans utiliser le mot-clé new est un appel de fonction normal.

③object.test() : Appel via un objet

④test.call/apply(obj) : Appel via un appel

<span style="font-size: 14px;">        var obj1 = {x: "obj"};<br/>        //声明一个函数a1,控制台输出函数中的上下文(this)        <br/>        function a1() {<br/>            console.log(this);<br/>        }<br/>        //函数a1调用call方法,传入obj1对象做上下文<br/>        a1.call(obj1);//Object {x: "obj"}<br/><br/>        var obj2 = {x: "obj"};     <br/>        function a2() {<br/>            console.log(this);<br/>        }<br/>        a2.apply(obj2);//Object {x: "obj"}<br/></span>

Remarque : Les fonctions de call() et apply() dans la fonction : elles sont toutes deux utilisées pour changer le point de ceci en

Le différence entre les 4 façons : La valeur de ceci est différente

<span style="font-size: 14px;">        var obj = {x: "obj"};<br/>        function fn1(){<br/>            console.log(this);<br/>            this.getColor=function (){<br/>                console.log(this);<br/>                return this.color;<br/>            }<br/>        }<br/>        fn1();//直接调用   输出第一个this-----》Window<br/>        var p = new fn1();//通过new来调用  输出第一个this-----》fn1{}(也就是输出p)<br/>        p.getColor();//通过对象来调用  输出第二个this-----》fn1{}(也就是输出p)<br/>        fn1.call(obj);//通过call来调用  输出第一个this-----》Object<br/>        fn1.apply(obj);//通过apply来调用   输出第一个this-----》Object<br/></span>

Résumé :

Appelez directement la fonction (fn1( )) : la sortie est Window , mais il y a une prémisse, il n'y a pas d'objet de liaison de liaison.

bind ne changera pas le this de la fonction d'origine, il génère simplement une nouvelle fonction et lie ceci

2.new Calling : This est l'objet nouvellement créé -----L'objet instance renvoyé fn1{}

3 Appel via l'objet : C'est l'objet qui appelle la méthode (cet objet )--. - Ce qui est renvoyé est le nouvel objet d'instance fn1{}

4.test.call/apply(obj) à appeler : L'objet spécifié ----L'objet obj est renvoyé

Remarque : l'appel de test() dans la fonction fn n'exécute pas la fonction fn. Uniquement lorsqu'elle est appelée à l'aide de call()/apply(), la fonction fn

(7) La différence entre les méthodes et les fonctions

<span style="font-size: 14px;">var arr = [1,2,3,4,5]<br/>var a =12;   // 变量:自由的<br/>arr.a= 5;     //属性:属于一个对象<br/>function show(){     //函数:自由的<br/>     alert(‘a’);<br/>}<br/>arr.fn = function(){   //方法:属于一个对象<br/>     alert(‘b’);<br/>}<br/>其实方法就是函数,只不过方法是有所属的对象。<br/><br/>我们所熟知的,将函数绑定到 click 事件<br/>语法:$(selector).click(function)<br/></span>

Déclarations de variables et de fonctions

1. Promotion de déclaration de variable et promotion de déclaration de fonction

a. ( La variable déclarée) est accessible avant l'instruction de définition, et la valeur est sous-définie

console.log(a);

var a =3;

//Analyse : Lors de la définition de a=3, vous pouvez accéder à la valeur de a, mais la valeur de a est sous-définie. Il s'agit de la promotion de la déclaration de variable .

//console.log(b);b=6; Mais b n'est pas possible, il faut le déclarer via var

b.函数声明提升:通过function声明的函数,在之前就可以直接调用,值为函数定义(对象object)

fn();

 function fn () {  console.log('1')  }

通过function声明的函数,在之前就可以直接调用,这个说明函数定义已经创建了。。

js引擎如何变量声明提升,函数声明提升?

     是通过预处理。

浏览器中的两大引擎:浏览器之所以能够将我们写的html代码、css代码以及js代码转换成一个炫丽的网页界面,是因为两大引擎的作用。
 →渲染引擎:解析html和css代码,转换成炫丽的静态界面

 →渲染引擎:解析html和css代码,转换成炫丽的静态界面

 →js引擎:解析并运行js代码,实现动态的交互效果。

js预解析:
  js代码在解释执行之前,有一个“预备的过程”。这个预备的过程被称为“预解析”。
  预备的过程做什么事情呢?

  把用var关键字所声明的变量名(仅仅只是变量名) 和 用函数声明的方式定义的函数(函数整体)提升到【当前执行环境】的顶部。

<span style="font-size: 14px;">console.log(a);<br/>var a=122;<br/>//这个会被解析成:<br/>var a;console.log(a);a=122;<br/>//所以不会报错,打印出undefined<br/><br/><br/>//2.函数声明方式创建的函数<br/>test1("hello");<br/>function test1(x){console.log(x)}<br/>//这个会被解析成:<br/>function test1(x){console.log(x)}<br/>test1("hello");<br/>//所以不会报错,打印出hello<br/><br/>//3.函数表达式的方式 创建的函数<br/>test2("hello js!");<br/>var test2=function test1(j){console.log(j)}<br/>//这个会被解析成:<br/>var test2;<br/>test2("hello js!");<br/>test2=function test1(j){console.log(j)}<br/>//所以会报错。test2没有定义函数。如果是这这样<br/>var test2=function test1(j){console.log(j)}<br/>test2("hello js!");<br/>//则不会报错。打印出hello js!</span>

关于函数声明,它最重要的一个特征就是函数声明提升,意思是执行代码之前先读取函数声明。这意味着可以把函数声明放在调用它的语句之后。如下代码可以正确执行:

<span style="font-size: 14px;">sum(1,2); //3  <br/>function sum(x,y){  <br/>    alert(x+y);  <br/>}  </span>

2.函数的参数

→形参:在定义函数时,括号中的参数列表就是形参。
  如:function 函数名(形参1,形参2,...){
   //执行代码
  }
→实参:在调用函数时,所传入的对应的实际的数据,就是实参。
  如:函数名(数据1,数据2,...);

→函数体内的 arguments
 在定义函数时,使用形参时,形参可以不写(不推荐),可以使用arguments 这个“伪数组”来获取所传入的实参。
  arguments[索引];   索引从0开始


  如:function 函数名(形参1,形参2,...){
   //执行代码
  }
→实参:在调用函数时,所传入的对应的实际的数据,就是实参。
  如:函数名(数据1,数据2,...);

→函数体内的 arguments
 在定义函数时,使用形参时,形参可以不写(不推荐),可以使用arguments 这个“伪数组”来获取所传入的实参。
  arguments[索引];   索引从0开始

3.返回函数的函数---返回值

return作用:终止函数,并返回数据。
使用方式:函数里若没有显示的使用return时,函数执行完后,最终返回undefined;
      return;  //执行到该句代码时,函数会终止,并返回undefined。
      return   数据;//执行到该句代码时,函数会终止,并返回指定的数据。

使用方式:函数里若没有显示的使用return时,函数执行完后,最终返回undefined;
      return;  //执行到该句代码时,函数会终止,并返回undefined。
      return   数据;//执行到该句代码时,函数会终止,并返回指定的数据。

案例:简易的计算器

<span style="font-size: 14px;"><script type="text/javascript"><br/>    var box = function(){<br/>        var a=1;<br/>        return function(){<br/>            alert(++a)<br/>        }<br/>    }<br/>    var newFunc = box();//因为上面返回return是函数体   所以box是函数<br/>    newFunc();//2<br/></script>                                                                                                                       <br/> 如果想让返回的函数立即执行,亦可以使用box()()来执行这段代码。</span>

4. 作用域作用域,指的是变量使用的范围。
→全局作用域:函数之外的环境(全局执行环境)
    全局变量:在全局执行环境中用var关键字所声明的变量就是全局变量,全局变量在程序中的任何地方都可以使用。
→局部作用域:一个函数就是一个独立的执行环境(函数体内就是一个局部执行环境)
 局部变量:在函数中用var关键字所声明的变量 或 函数定义中的形参,仅仅只能够在本函数(本作用域中)中使用。
→注意:
     情况一: 当全局变量 和 局部变量命名一样时,在函数中使用该变量时,会优先使用函数本身中定义的局部变量。
     情况二:关于形参,其实就相当于在函数内用var关键字声明了变量。
  如:function test(a,b){
  //var a,b;    
  }

→ 再看变量声明提升:

<span style="font-size: 14px;">var scope = &#39;global&#39;;<br/>function f(){<br/>    console.log(scope);<br/>    var scope = &#39;local&#39;;<br/>    console.log(scope);<br/>}<br/>由于函数内声明提升,所以上面的代码实际上是这样的<br/><br/>var scope = &#39;global&#39;;<br/>function f(){<br/>    var scope;    //变量声明提升到函数顶部<br/>    console.log(scope);<br/>    scope = &#39;local&#39;;    //变量初始化依然保留在原来的位置<br/>    console.log(scope);<br/>}<br/>经过这样变形之后,答案就就非常明显了。由于scope在第一个console.log(scope)<br/>语句之前就已经定义了,但是并没有赋值,因此此时scope的指是undefined.<br/>第二个console.log(scope)语句之前,scope已经完成赋值为’local’,所以输出的结果是local。</span>

→ JavaScript中没有块级作用域
  就是在 选择语句 或 循环语句 中定义的变量不像是在函数体内一样定义的变量是局部变量,而是全局变量

5.匿名函数 和 自执行函数

①匿名函数(简称IIFE)

顾名思义就是没有名字的函数。

a.function(){}这样定义的函数在语法上是错误的(因为它没有函数名字)。

b.  (function(){....})
   !function(){....}

   -function(){....}

var a = function(){......}

若是加上一些运算符的话,该函数就不会产生错误,此时的函数被称为“匿名函数”。

注意:(function(){//这里是块级作用域  })

以上代码的这种方式就是模仿了块级作用域(通常成为私有作用域);定义并立即调用了一个匿名函数。经函数声明包含在一对圆括号中,表示它实际上是一个函数表达式。而紧随其后的另一对圆括号会立即调用这个函数。

②自我执行函数(其实就是执行匿名函数):即定义和调用合为一体
  (function(){ // (匿名函数)();第一圆括号放匿名函数,第二个圆括号执行
      alert(1);
    })();
匿名函数定义玩之后可以即刻执行。

→匿名函数的作用:

  避免全局变量污染以及命名冲突。

补充:

<span style="font-size: 14px;">//1.把匿名函数自我执行的返回值赋给变量:<br/>    var box =  (function (){           <br/>           console.log(&#39;Lee&#39;);<br/>           return 3;<br/>    })();         //打印”Lee”;<br/>    console.log(box);   //如果没有return 3的话,打印出来就是 undefined<br/>	<br/>	//2.自我执行匿名函数的传参<br/>    (function (age){<br/>         alert(age);<br/>    })(100);          //弹出100<br/></span>
<span style="font-size: 14px;">自执行函数的三种写法<br/>var result = function (){<br/>    alert(2);<br/>}();<br/>另一种语法也可得到同样结果:<br/>var result = (function () {<br/>    console.log(2);<br/>})();<br/>将函数返回值分配给变量:<br/>var result = (function () {<br/>    return 2;<br/>}());<br/></span>



三. 回调函数

回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。我们就说函数A叫做回调函数。

→ 函数是一种实际的数据。

→ 在定义函数时,是可以在括号中定义形参的。

→ 在括号中的形参就相当于变量。而变量将来要介绍实际的数据,实参。

<span style="font-size: 14px;">/*函数是一种数据。所以可以当做实参来使用*/<br/>        	function fn(f){<br/>        		f();<br/>        	}<br/>        	var a = function(){<br/>        		alert("我是回调的函数");<br/>        	}<br/>        	fn(a);//fn是主函数,参数为a函数本身,所以a是回调函数<br/><br/><br/>            fn(function(){<br/>                alert("我是回调过来的");<br/>            })//在fn的函数里直接调用函数,这个被调用的函数也就是回调函数<br/></span>

b.将回调函数的参数作为与回调函数同等级的参数进行传递


总结明了同时满足这三个条件就是回调函数:

*你定义的函数

*你没有直接调养

*但最终它会执行(在特定条件和时刻)

(2).常用的回调函数

*DOM事件函数

*定时函数

*ajax函数

*生命周期回调函数(组件,对象)

<span style="font-size: 14px;">//DOM事件函数<br/>            document.getElementById(&#39;id&#39;).onclick=function(){<br/>                alert(&#39;点击事件。。&#39;)<br/>            }<br/>            //定时函数<br/>            setTimeout(function(){<br/>                console.log(&#39;到点了&#39;);<br/>            },10000)<br/></span>


(3).匿名函数

如果没有名称(函数表达式),就叫做匿名回调函数

作用:a.隐藏内部实现b.不污染外部命名空间

<span style="font-size: 14px;">(function(){<br/>                var a = 123;<br/>                function foo(){<br/>                    console.log(a)<br/>                }<br/>            })();</span>

四.函数中this

1.this是什么?

*一个关键字,一个内置的引用变量

*在函数中都可以直接使用this

*this代表当前函数的调用对象

*在定义函数时,this还没有确定,只有在执行时才动态绑定的

记住:跟函数定义没关系,跟函数的执行有大大的关系。总之就是:函数在哪里调用才决定了this到底引用的是啥

2.如何确定this的值?

①test():直接调用
②new test():通过new来调用
③object.test():通过对象来调用
④test.call/apply(obj):通过call来调用

1.直接调用函数(fn1()),输出的是Window,但是有一个前提,就没有bind绑定对象。

bind不会改变原有函数的this,只是产生了一个新的函数,并绑定的this

2.new调用,则返回的是new 的实例对象fn1{}

3.通过对象来调用,返回的是new 的实例对象fn1{}

4.test.call/apply(obj)来调用,返回的是obj对象

注意:

(1).执行函数时:有步骤
        a.执行函数定义(也就是执行这整块function Person(color){...}代码,把这个整块看成一句语句,就是函数定义):本质是创建函数对象
        b.执行/调用 函数Person('red');
(2).函数对象:函数首先是一个对象,所以可以通过“ . ”来确定它内部的属性以及方法。
        如我用" () "   a() ,此时a则是函数,如a.yy();这时a就称函数对象。可以通过“ . ”来判断是否是函数对象
(3)通过对象调用的时候,称方法:p.getColor();其他的时候称函数(p.setColor.call(obj,'black');)p.setColor获取是一个属性值,而这个属性值就是函数

<span style="font-size: 14px;">function Person(color){<br/>console.log(this);<br/>this.color=color;<br/>this.getColor=function (){<br/>    console.log(this);<br/>    return this.color;<br/>}<br/>this.setColor=function (color){<br/>    console.log(this);<br/>    return this.color;<br/>}<br/>}<br/>Person(&#39;red&#39;);//输出是第一个 console.log(this);-----Window<br/>// this.getColor方法内的console.log(this)是不执行的,但是getColor函数定义出来了<br/><br/>var p = new Person("yello");//输出是第一个 console.log(this);-----Person {}(就是p) <br/><br/>p.getColor();<br/>//输出是第二个 console.log(this);-----Person {color: "yello"}(就是p) <br/><br/>var obj={};<br/>p.setColor.call(obj,&#39;black&#39;);<br/>//输出是第三个 console.log(this); ---obj  通过函数对象的call方法来执行函数<br/><br/>var text=p.setColor;//把p.setColor的属性值(函数)赋值给text<br/>text();//直接调用 输出的都是 Window<br/><br/>function fun1(){<br/>function fun2(){<br/>    console.log(this);<br/>}<br/>fun2();//直接调用 输出的都是 Window<br/>}<br/>fun1();<br/><br/><br/>//注意:fn.bind()<br/>function fn(){<br/>console.log(this)<br/>}<br/>const obj2={}<br/>const fn2=fn.bind(obj2);<br/>//bind不会改变原有函数的this,只是产生了一个新的函数,并绑定的this<br/>fn();//直接调用 输出的都是 Window<br/>fn2();//输出的是 obj2</span>

五.递归

1.递归的官方概念:

  程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

2.递归的案例:
如一组有规律的年龄
  10 、12、14、16、18、20、22、24......
  求第n个人的年龄?

  图解分析:
  两个阶段:回推阶段(前进)、递推阶段(返回)
  一个条件:边界条件;第一个人的年龄为10


<span   style="max-width:90%">function getAge(n){<br/>        		if(n==1){ //边界条件<br/>        			return 10;<br/>        		}else {<br/>        			return getAge(n-1) + 2;<br/>        		}<br/>        	}<br/><br/>        	var age = getAge(5);<br/>        	alert(age);<br/></span>

相关推荐:

JavaScript函数绑定用法解析

实例讲解JavaScript函数绑定用法

详细介绍JavaScript函数的作用域与this指向

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn