精华内容
下载资源
问答
  • 函数其它 匿名函数 匿名函数:没有名字的函数 ...自调用函数 匿名函数不能通过直接调用来执行,因此可以通过匿名函数的自调用的方式来执行 (function () { alert(123); })(); 函数是一种数据类型 function...

    函数其它

    匿名函数

    匿名函数:没有名字的函数

    匿名函数如何使用:

    将匿名函数赋值给一个变量,这样就可以通过变量进行调用
    匿名函数自调用
    

    关于自执行函数(匿名函数自调用)的作用:防止全局变量污染。

    自调用函数

    匿名函数不能通过直接调用来执行,因此可以通过匿名函数的自调用的方式来执行

    (function () {
      alert(123);
    })();
    

    函数是一种数据类型

    function fn() {}
    console.log(typeof fn);
    
    • 函数作为参数

    因为函数也是一种类型,可以把函数作为两一个函数的参数,在两一个函数中调用

    • 函数做为返回值

    因为函数是一种类型,所以可以把函数可以作为返回值从函数内部返回,这种用法在后面很常见。

    function fn(b) {
      var a = 10;
      return function () {
        alert(a+b);
      }
    }
    fn(15)();
    

    代码规范

    1.命名规范	
    2.变量规范   
    	var name = 'zs';	
    3.注释规范
    	// 这里是注释
    4.空格规范
    5.换行规范
    	var arr = [1, 2, 3, 4];
    	if (a > b) {
          
    	}
    	for(var i = 0; i < 10; i++) {
          
    	}
    	function fn() {
          
    	}
    
    展开全文
  • JS 自执行函数又称为 IIFE,指声明一个匿名函数,然后马上调用,这种函数一般称为一次性函数、自调用函数等。 什么是函数声明与函数表达式: // 函数声明语句 function demo() // 函数表达式 var demo = function() ...

    前言

    JS 自执行函数又称为 IIFE,指声明一个匿名函数,然后马上调用,这种函数一般称为一次性函数、自调用函数等。

    什么是函数声明与函数表达式:

    // 函数声明语句
    function demo()
    // 函数表达式
    var demo = function()
    

    IIFE常见的写法:

    // one
    (function (){
    	...
    })();
    
    // two
    (function (){
     	...
    }())
    
    // three(通过与或操作符)
    false || function (){
      	...
    }()
    
    1 && function (){
    	...
    }()
    
    0 , function (){
    	...
    }()
    
    // four(通过操作符)
    var self = (function (){
      	...
    })()
    
    // five(通过一元运算符)
    ! function (){
    	...
    }()
    
    + function (){
      	...
    }()
    
    - function (){
      	...
    }()
    
    // six(通过new)
    new function (){
    	...
    }
    

    如上四种方法中,其第三种方法 three(通过与或操作符) 完成实现自执行函数一般使用在打包工具里面,比如 webpack 打包后你会经常看到: ” 0,functtion(){}() “ 。


    还需要额外注意第四种方法 four(通过操作符) 完成实现自执行函数的话,这种方法会占用命名空间,不推荐使用。


    其中第五种方法 five(通过一元运算符) 完成实现自执行函数的话,一元运算符仍可以将函数声明转换为函数表达式,比如 bootstrap 框架中经常使用。但是性能略低,因为一元运算符要进行一次数字类型的转换。


    注意:在使用时在函数前加上 " ;(分号) ",防止解释器错误解析,又避免了压缩或者打包时变为函数。

    为什么要使用自执行函数

    (1)避免作用域命名污染(创建独立作用域):

    防止变量弥散到全局,以免各种 JS 库冲突。隔离作用域避免污染,截断作用域链,避免闭包造成引用变量无法释放等。

    (2)解决全局变量污染问题:

    如 JQuery 里面暴露给全局作用域 $ 和 query 两个变量,为了解决这个问题,我们可以将 window.jq 作为一个实参传递给一个立即执行的匿名函数,这样的话我们再次命名使用 $ 或者 query 就不会有命名冲突了。
    有兴趣可以查看 https://blog.csdn.net/weixin_44198965/article/details/100712467
    (3)有利于代码压缩:

    这样可以用简单字符串代替

    (4)颠倒代码执行顺序:

    // UMD通用模块规范
    (function(){})(bb())
    
    console.log(12)
    
    function bb(){
    
    console.log(22)
    
    }//打印顺序为:22,12
    

    (5)模仿块级作用域:

    作用域的内部可以访问到外部,外部不可以访问到内部,JS 作用域的缺陷就是没有块级作用域,好在ES6加入了一丢丢。

    IIFE原理

    JavaScript 引擎在预编译阶段处理函数,但由于 ( function () {} ) 是表达式,所以 JS 在预编译阶段会忽略它;在 JavaScript 代码执行时,执行到 ( function () {} ) 会对它求值,得到一个返回值,这个返回值就是一个函数,所以在遇到 () 时,就会去执行该函数。总之,立即执行匿名函数就是把函数变成一个表达式,让 JavaScript 引擎在预编译阶段忽略它,然后在执行阶段解析它,然后碰到 () 就直接执行。

    (end)

    展开全文
  • 从逻辑上讲,栈帧就是一个函数执行的环境:函数调用框架、函数参数、函数的局部变量、函数执行完后返回到哪里等等。栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所...

    1、什么是栈帧?

    栈帧也叫过程活动记录,是编译器用来实现函数调用过程的一种数据结构。C语言中,每个栈帧对应着一个未运行完的函数。从逻辑上讲,栈帧就是一个函数执行的环境:函数调用框架、函数参数、函数的局部变量、函数执行完后返回到哪里等等。栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。

    2、Add()函数的调用过程

    我们以Add()函数为例深入的研究一下函数的调用过程。
    先看一段简单的代码:

    复制代码

     1 #include <stdio. h>
     2 int Add(int x, int y)
     3 {
     4 int z = 0;
     5 z = x + y;
     6 return z;
     7 }
     8 int main()
     9 {
    10 int a = 10;
    11 int b = 20;
    12 int ret = Add(a, b) ;
    13 printf("ret = %d\n", ret) ;
    14 return 0;
    15 }

    复制代码

    当讲程序调试的时候, 查看【调用堆栈】(按F10进入调试-窗口-调用堆栈,或按快捷键ctrl+alt+C) ,用VS2015调试 如下图:

    如果用版本更老的,或其他如VC6.0等编辑器则可以看到更多信息,VS2008调试如图:

    我们发现其实main函数在 __tmai nCRTStartup 函数中调用的,而 __tmai nCRTStartup 函数是在 mai nCRTStartup 被调用的。我们知道每一次函数调用都是一个过程。这个过程我们通常称之为: 函数的调用过程。这个过程要为函数开辟栈空间, 用于本次函数的调用中临时变量的保存、 现场保护。 这块栈空间我们称之为函数栈帧。
    而栈帧的维护我们必须了解ebp和esp两个寄存器。 在函数调用的过程中这两个寄存器存放了维护这个栈的栈底和栈顶指针。比如:调用main函数, 我们为main函数分配栈帧空间, 那么栈帧维护如下:
    ebp存放了指向函数栈帧栈底的地址。esp存放了指向函数栈帧栈顶的地址。
    注意:ebp指向当前位于系统栈最上边一个栈帧的底部,而不是系统栈的底部。严格说来,“栈帧底部”和“栈底”是不同的概念;ESP所指的栈帧顶部和系统栈的顶部是同一个位置。

    1 . 从main函数的地方开始, 要展开main函数的调用就得为main函数创建栈帧, 那我们先来看main函数栈帧的创建。转到反汇编可以更清晰的看到过程:

    过程分析:

    a.首先mainCRTStartup(),__mainCRTStartup()函数的调用,调main()函数;

    b.将ebp压栈处理,保存指向栈底的ebp的地址(方便函数返回之后的现场恢复),此时esp指向新的栈顶位置;

    c.将esp的值赋给ebp,产生新的ebp;

    d.给esp减去一个16进制数0E4H(为main函数预开辟空间);

    e.push ebx、esi、edi;

    f.lea指令,加载有效地址;

    g.初始化预开辟的空间为0xcccccccc;

    h.创建变量a与b。

    2. 接下来是Add函数的调用。

    参数传递过程:

     过程分析:

    a.将b存入寄存器eax,再将将eax压栈;(传参过程,从左向右传递)

    b.将a存入寄存器ecx,再将将ecx压栈;

    c.call指令的调用,先要压栈call指令下一条指令的 地址,然后跳转(push+jmp)到Add()函数的地方(__cdecl调用约定)。
    执行call指令的时候按F11 , 来到了这里。
    再按F11 就进入Add函数的执行代码处。Add函数栈帧的创建:

    过程分析:

    a.首先将main()函数ebp压栈处理,保存指向main()函数栈帧底部的ebp的地址(方便函数返回之后的现场恢复),此时esp指向新的栈顶位置;

    b.将esp的值赋给ebp,产生新的ebp,即Add()函数栈帧的ebp;

    c.给esp减去一个16进制数0E4H(为Add()函数预开辟空间);

    d.push ebx、esi、edi;

    e.lea指令,加载有效地址;

    f.初始化预开辟的空间为0xcccccccc;

    g.创建变量z;

    h.获取形参的a和b再相加,将结果存储到z中;

    i.将结果存储到eax寄存器,通过寄存器带回函数的返回值。
    剩下的就是是函数返回部分:

    过程分析:

    a.pop3次,edi、esi、ebx依次出栈,esp 会向下移动;

    b.将ebp赋给esp,使esp指向ebp指向的地方

    c.ebp 出栈,将出栈的内容给ebp(即main()函数ebp),回到main()函数的栈帧;

    d.ret 指令,出栈一次,并将出栈的内容当做地址,并跳转到该地址处(pop+jmp)。

    注: 栈帧这部分内容在不同的编译器上实现存在差异, 但是思想都是一致的。

    栈帧的一般总结:

    1. 堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间:
    ➢ 函数调用框架;
    ➢ 传递参数;
    ➢ 保存返回地址;
    ➢ 提供局部变量空间;
    ➢ 等等。
    以x86体系结构为例
    2. 堆栈寄存器和堆栈操作
     堆栈相关的寄存器
    ➢ esp,堆栈指针(stack pointer)
    ➢ ebp,基址指针(base pointer)
    堆栈操作
    ➢ push 栈顶地址减少4个字节(32位)
    ➢ pop 栈顶地址增加4个字节
    ❖ ebp在C语言中用作记录当前函数调用基址
    3. 利用堆栈实现函数调用和返回
    ❖其他关键寄存器
    ➢ cs : eip:总是指向下一条的指令地址
    ● 顺序执行:总是指向地址连续的下一条指令
    ● 跳转/分支:执行这样的指令的时候, cs : eip的值会根据程序需要被修改
    ● call:将当前cs : eip的值压入栈顶, cs : eip指向被调用函数的入口地址
    ● ret:从栈顶弹出原来保存在这里的cs : eip的值,放在cs : eip中
    ● 发生中断时???
    4. 函数堆栈框架的形成

    ❖call xxx
    ➢执行call之前;
    ➢执行call时,cs:eip原来的值指向call下一条指令,该值被保存到栈顶,然后cs:eip的值指向xxx的入口地址
    ❖进入xxx
    ➢第一条指令:pushl %ebp
    ➢第二条指令:movl %esp,%ebp
    ➢函数体中的常规操作,压栈,出栈等
    ❖退出xxx
    movl %ebp,%esp
    popl %ebp
    ret

    5. 堆和栈的关系
    我们平时说的堆栈其实是指栈,而实际上堆和栈是两种不同的内存分配。简单罗列如下各方面的异同点。
    1).堆需要用户在程序中显式申请,栈不用,由系统自动完成。申请/释放堆内存的API,在C中是malloc/free,在C++中是new/delete。申请与释放一定要配对使用,否则会造成内存泄漏(memory leak),久而久之系统就无内存可用了,出现OOM(Out Of Memory)错误。一般在return/exit或break/continue等语句时容易忘记释放内存,所以检查内存泄漏的代码时要关注这些语句,看它们前面是否有必要的释放语句free/delete。
    2).堆的空间比较大,栈比较小。所以申请大的内存一般在堆中申请;栈上不要有较大的内存使用,比如大的静态数组;而且除非算法必要,否则一般不要使用较深的迭代函数调用,那样栈消耗内存会随着迭代次数的增加飞涨。
    3).关于生命周期。栈较短,随着函数退出或返回,本函数的栈就完成了使用;堆就要看什么时候释放,生命周期就什么时候结束。
    我们发现解析Coredump还是跟栈的关系相对紧密,跟堆的关系是有一种产
    生Coredump的原因是访问堆内存出错。

    为什么研究栈帧?看一个题目 :
    在VC6.0环境中, 下面代码的结果是什么?

    复制代码

     1 #include <stdi o. h>
     2 void fun()
     3 {
     4 int tmp = 10;
     5 int *p = (int *) (*(&tmp+1) ) ;
     6 *(p-1) = 20;
     7 }
     8 int main()
     9 {
    10 int a =0;
    11 fun() ;
    12 printf("a = %d\n", a) ;
    13 return 0;
    14 }

    复制代码

    事实上在不同平台下这段代码有不同的输出,可自行验证。

    展开全文
  • 一,自调用匿名函数有两种方式: 第一种: (function(参数){....}(传入参数)) --->...说明:jquery就是采用这种方式,这种方式的原理: 原来我们调用函数的方式是,先定义,在进行函数名调用 function f...

    一,自调用匿名函数

    有两种方式:
           第一种: (function(参数){....}(传入参数))    --->括号内的语句被强制执行

          

     第二种: (function(参数){...})(传入参数)     --->说明:jquery就是采用这种方式,这种方式的原理:  原来我们调用函数的方式是,先定义,在进行函数名调用
            function funName(){
            alert("hello world");
            }
            funName(); //调用
            其原理是通过函数名(引用)去找实际的函数定义,  那么我们这种自调用就很好理解了,是一定义函数就使用,而不是通过函数名去找定义
            即如果 你使用 (function(参数){...})的形式, 则相当于你定义了一个函数并执行了定义, 之后使用(参数),即是再进行自调用,即类似   函数名(参数) ,只不过这里没有函数名,而是变成函数定义实体,直接传入参数即可
           

    自调用匿名函数作用:    使内部变量不会与外部用户自定义的全局变量产生冲突,例如一个函数重名问题:如果不是自调用的函数,那么必须有函数名,并且暴露给外部用户调用,那么就有可能产生函数重名问题:用户的自定义了一个相同的函数名称


    自调用函数的形式研究: 在js中, "()"可以强制执行,第二种可以将函数括号换为其他类型, 例如-,+,new 等等,只要是能够进行通顺运算的(会把函数定义当成一个变量的方式执行起来)【-,+,new是可以直接放在变量前面的,如果是*则需要在*前加数字才通顺 例如1*varName】




    二,作用域:

    对象变量


      1. 变量前有this:即this.varName的形式:公有变量,可以直接访问
      2.对象前没有this:私有变量或者全局变量,,无法直接访问


      1).私有变量:在对象内以var定义的变量, 如: var varName='xxxx', 不能直接访问, 需要setter和getter函数访问


      2). 全局变量: 在对象外部的变量 或者 在函数内部直接使用变量名的形式,即没有var或this的形式, 例如 varName="这是全局变量", 这样子就定义了一个全局变量

    全局变量不能以 对象.变量的形式访问, 但是可以直接以 变量名的形式访问, 例如在程序中要访问可以: alert(varName);即输出"这是全局变量"
    成员函数


      1. 函数前加this: 即 this.functionName的形式:公共函数,可以直接访问,setter和getter方法即用这样定义


      2.对象前没加this: 即function functionName(){}的形式,私有函数,只能在对象内部使用

    成员函数如何访问对象变量:


      1,对象公共变量: 本身不用返回外部也可取到, 如果要访问,使用this.varName(因为在对象中就是这样定义的)


      2.全局变量: 直接使用返回 varName的形式(因为本身就可以在任何地方使用 varName的形式)


      3.私有变量: 也是返回 varName的形式,不能使用this,this代表当前函数
    三,闭包:
      function Person(){
      var i = 1;
      function functionName(){
        alert(++i);
      }
      return functionName;
    }
    var result = Person();
    result();//得到2
    result(); //得到3
    说明:闭包:functionName称为闭包,网上通俗解释为 函数中的函数
    我更愿意理解为   对象中的函数,在作用域里讲过, 通过function functionName(){}的方式定义的是私有成员函数,只能给对象内部使用;
    要是愿意,完全可以将 return functionNname 的functionName 替换为原 functionName函数的定义,效果一样
    而在调用端, var result=Person(); 实例化对象(可以使用new Person()),result() 是调用对象,而实例化的对象只有一个,当然每调用一次i值就会增加

    如果,实例化两个对象,那么其实两个对象的i值是不会互相影响的


    四,js原型,prototype<略>


    通过 对象.prototype.XXX 可以给原有的对象 增加成员或者修改成员,(给对象进行扩展和修改),也是js中一个比较重要的知识点


    掌握了上述的四个知识之后,就可以尝试去看看JQuery库的源码了,jquery通过自调用将jQuery【$】赋给window.jQuery,并在这个对象定义了很多成员和扩展,因此我们客户端才可以直接通过 [window.]jQuery或$的方式使用JQuery库和其里面的方法
    ---------------------


    转载于:https://www.cnblogs.com/data-captain/p/9861274.html

    展开全文
  • 需要先强调一个要点,即自调用函数是在它被定义时候运行,而通常不是等待被调用,但是在本文实例中,自调用函数不仅被调用了,并且还运行了一部分,这来自于它有趣结构——自调用函数与闭包结合。
  • 什么是自调用匿名函数? 答案就是:通过创建一个自调用...自调用匿名函数的写法有三种。 第一种方法:  (function (){  //....  })(); 第一种方法:  (function (){  //....  }()); 第一种方法: ...
  • Self-Invoking Anonymous Function,即...该函数的作用是在应用中初始化或做一次性工作。 普通匿名函数: function () { alert('hello'); } 自调用无参匿名函数: (function(){ alert('hello,...
  • 1,arguments是一个比较特别对象,每个函数中都有一个arguments,它接收函数传入参数,以数组形式存放在 arguments,可遍历 //1,需求:求任意数最大值 function getMax(){ var Max = arguments[0]; //...
  • 自执行(自调用函数可以创建独立的作用域避免全局污染,以及项目中多个js文件中全局变量或方法命名冲突的问题; 用法:(函数)(实参),()中可以传递参数,下面例子是自调用匿名函数,也可以设置函数名; 在其他...
  • 自调用匿名函数

    2017-09-24 14:35:48
    通过创建一个自调用匿名函数,创建一个特殊的函数作用域,该作用域中代码不会和已有同名函数,方法和变量及第三库冲突 自调用匿名函数写法 方法一 (function(){  //... })(); 方法二 ...
  • (function( window, undefined ) {var jQuery = ...通过创建一个调用匿名函数,创建了一个特殊的函数作用域,该作用域中代码不会和已有同名函数、方法和变量以及第三方库冲突。由于 jQuery 会被应用在成千上万...
  • 构造函数和析构函数的调用顺序 构造函数的调用顺序: 当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达最底层的目标派生类的构造函数为止。 析构函数的调用书序:...
  • 函数自调用就是,函数在创建同时会自动调用,匿名函数参数外部是访问不到,要通过window将参数挂载到全局,成为全局变量,从而让外界访问到(function(win){//形参,此处接受是window var num= 13//定义一...
  • 编写自调用匿名函数的结构一般如下: ;(function( window, undefined ) { // your code })(window); 传入的参数window,和参数列表中的undefined怎么解释? 1、传入的参数window  把全局的Window对象传...
  • 二、递归的作用: 大大较少了程序的代码量。 三、经典递归的使用场景 1.深拷贝 // 深拷贝 function deepClone(obj) { // 判断是否是数组 let newobj=Array.isArray(obj)?[]:{}; // 判断是否为简单数值类型 if ...
  • 函数的闭包与自调用

    2016-06-30 15:58:37
    函数自调用: var result = function (x) { return x + 1; }(3); // => result 值为4 在函数末尾加上()并传入参数。 闭包函数: 实现外部作用域访问内部作用域中变量方法叫做闭包。
  • 通过创建一个调用匿名函数,创建了一个特殊的函数作用域,该作用域中代码不会和已有同名函数、方法和变量以及第三方库冲突。 //写法1 常用也是jqueryr所采用 (function(){ //功能实现 })(); //写法...
  • 分类:系统库函数,标准C库 ·libc 1):必须要引入头文件#include函数声明 2):根据函数库函数原型,调用函数 用户自定义函数 bubble_sort() , ruprint(),除了需要提供函数原型之外,还需要提供函数实现。...
  • 程序基石系列之自动调用函数

    千次阅读 2014-02-12 16:38:17
    当对象超了它的作用域时,编译器将自动调用函数。即在对象的定义点处构造函数调用,但析函数调用的惟一证据是包含此对象的右括号。 /* * Constructors &Destructors * Eclispe CDT */ #include using ...
  • 函数声明必须以function字段开头,xxx是该函数的函数名,小括号中的a,b,c是该函数引用的参数,大括号中是该函数的具体方法。使用函数声明的函数会提升其优先度,因此我们可以在同一作用域的任何区域声明,不会影响...
  • 如果需要在函数内部给一个定义在函数外的变量赋值,那么这个变量的作用域不能是局部的,而应该是全局的。能够同时作用于函数内外的变量称为全局变量,它通过global关键字来声明,如例所示。 此处需注意,如果不...
  • 文章目录js高级 第四天函数调用方式this指向改变this指向方法IIFE执行函数作用域划分对象概念创建对象对象遍历 函数调用方式 1.普通函数函数(); 2.对象方法:对象名.方法名() 3.构造函数:new 构造函数名();...
  • :常高伟专栏http://blog.csdn.net/chgaowei/article/details/6692666 前几天为新员工写一个简单测试框架,可让他们方便写测试用例并且执行。期间遇到一个问题就是如何让他们增加测试用例而用不影响测试...
  • 在Python中,main函数的主要作用就是你写的模块既可以导入到别的模块中用,也可以在模块本身执行使用。下面就来了解具体使用操作吧。编写简单的函数并调用:def show():print("这是一个简单的函数")print("无论如何...
  • 意思:在函数内部使用,代表当前函数的引用!也就是名字. 作用:降低代码的耦合度~ 耦合度:一处代码的修改导致其他代码发生改变~ function f (){ arguments.callee(); } 例如:实现阶乘的函数; function f (n){ ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,487
精华内容 2,594
关键字:

自调用函数的作用