美文网首页
函数与作用域

函数与作用域

作者: 饥人谷_啦啦啦 | 来源:发表于2017-06-15 23:15 被阅读0次

1. 函数声明和函数表达式有什么区别?

  • 函数声明:
    形式上 function fuctionName(){//statement};声明了一个名字为functionName的函数,浏览器解析的时候,先要做函数声明前置,在globlecontext的AO中,声明此函数,此时,你在全球作用域下(包括函数声明之前的位置)调用,都可以找到这个函数。

  • 函数表达式:
    形式上 var someThing=fuction (){//statement};虽然这也是声明了一个函数(匿名的),但实际上浏览器解析的时候,先做的是变量提升,在globlecontext的AO中,声明的是一个变量,假如,在函数声明之前调用该函数,是不能够找到这个函数的,因为调用的时候必然要调用的someThing这个变量,但是变量值在提升变量的时候未给出。

2.什么是变量的声明前置?什么是函数的声明前置

  • 变量的声明前置:
    变量的声明前置就是在函数内部,首先要做的事也是类似于浏览器做变量提升,先在当前上下文的AO中声明这个变量。

  • 函数的声明前置:
    函数的声明前置是,当我们用函数声明来声明一个函数时,函数就会在至当前上下文的AO中声明这个这个函数,同时,在函数内部的上下文的scope中,给声明的函数开辟一个空间,并指向父元素的AO.

3.arguments是什么?

  • arguments是一个伪类数组,目前仅仅知道,他是一个函数内部自带的一个类似于数组的参数,我们可以调用arguments[],来获取传入函数内部的参数,并且支持索引,支持length属性。

4.函数的"重载"怎样实现?

  • 首先,JS中不同于其他语言,没有重载,例如其他语言中,我们可以设定。但是我们可以控制函数体内部的逻辑语句来实现重载。

例如:

<script language="JavaScript"> 
function f(length) 
{ 
    alert("高为:"+length); 
} 

function f(length,width) 
{ 
    alert("高为:"+length+",宽为:"+width); 
} 
</srcipt>
/* 上面这个段代码行不通,第一个函数会被第二个覆盖,不能实现 f(10)想要的效果。*/

但是我们可以这么做

<script language="JavaScript"> 
function f(length) 
{ 
    var len= arguments.length; 
    if(1 == len) 
    { 
        var width = arguments[1]; 
        alert("高为:"+length+",宽为:"+width); 
    } 
    else 
    { 
        alert("高为:"+length); 
    } 
} 
</srcipt>

5.立即执行函数表达式是什么?有什么作用?

  • 立即执行表达式是什么?
    (function (){})();
    (function(){}());
    上面就是两个常见的立即执行表达式,当我们建立一个匿名函数时,并希望他执行时,我们想到可以这样 function (){}(); 但是实际上,语法上不对,因为浏览器读到这里时,会认为这是一个函数声明,但是没有给出函数名字,所以会报错。但是我们在 function (){}加上括号,意义就不一样了,因为JS中小括号内部是一个表达式,表达式后面加括号,函数可以立即执行的, 和函数表达式声明一样
var something= functiong (){
  console.log ( "hello")
}();

所以,我们只需要让浏览器明白,我们前面function (){} 是一个函数表达式就可以了,类似的方法有许多,而已加上各种运算符,让浏览器知道,我们这是一个函数表达式,这就可以了。类似的有很多。

  • 为什么要用立即执行函数表达式?

    因为JS并没有块级作用域的概念,你在全局或者局部声明的变量 极有可能会被自己或者他人覆盖掉,为了保护这些的变量,我们可以给他加上一层外壳,封装起来,这样,外部变量就不会对内部的变量造成影响了。

求n!,用递归来实现

function doRecursion(n){
    if(n<0){
      console.log('You input a wrong number');
    }
    else if(n===0||n===1){
        return 1;
    }
    else if(n>0){
      return n*multiply(n-1);
    }
}

7.以下代码输出什么?

    function getInfo(name, age, sex){
        console.log('name:',name);
        console.log('age:', age);
        console.log('sex:', sex);
        console.log(arguments);
        arguments[0] = 'valley';
        console.log('name', name);
    }

    getInfo('饥人谷', 2, '男'); 
getInfo('小谷', 3);
getInfo('男');

// 倒数第三行调用函数 ,输出 name: 饥人谷,age:2,sex:男;['饥人谷',2,'男‘],name:valley
// 倒数第二行调用函数,输出 name:小谷,age:3;sex:undefined;['小谷',3,];name:valley;
//最后一行调用函数,输出name:男,age:undefined;sex:undefined;['男'];
name:valley;

8.写一个函数,返回参数的平方和?

   function sumOfSquares(){
      var sum=0;
      for (var i=0;i<arguments.length;i++){
        sum=sum+arguments[i]*arguments[i];
      }
      return sum;
   }
   var result = sumOfSquares(2,3,4);
   var result2 = sumOfSquares(1,3);
   console.log(result) ;
   console.log(result2) ;

9.如下代码的输出?为什么

    console.log(a); //undefined,变量提升,有变量a,但是没有值。
    var a = 1;
    console.log(b);//error ,没有定义这个变量。

10.如下代码的输出?为什么

    sayName('world'); //hello,world.
    sayAge(10);//报错 。
    function sayName(name){
        console.log('hello ', name);
    }
    var sayAge = function(age){
        console.log(age);
    };

第一个函数能输出是因为,函数声明前置,可以找到globleContext的OA中有这个函数,然后就可以去执行这个函数的上下文。
第二个变量提升,浏览器不知道sayAge(10)是什么意思,如果放在函数表达式后面,浏览器就知道原来这个sayAge()是一个函数表达式,就会执行了。

11.如下代码输出什么? 写出作用域链查找过程伪代码

var x = 10
bar() 
function foo() {
  console.log(x)
}
function bar(){
  var x = 30
  foo()
}

第一步:

globleContext{
  A0:{
  x:10,
  function foo(),
  bar(),
  }
  scope:null;
}
foo().[[scope]]=globleContext.AO
bar().[[scope]]=globleContext.AO

第二步:

执行bar();
在globloContext.AO中找到了 bar();
调用bar();进入bar()函数的barContext
barContext:{
  AO:{
    x:30,
  }
  scope:globleContext.AO
}
barContext.AO中没有找到 foo();然后去scope中找,scope指向globleContext.AO, 找到右foo();调用foo();
fooContext:{
  AO:{
    x:undefined,
  }
  scope:globleContext.AO
}
执行console.log(x);
但是在AO中没有找到,去scope中找到指向globleContext.AO,找到x的值为10,所以,最终结果就是10。

12.如下代码输出什么? 写出作用域链查找过程伪代码

var x = 10;
bar() 
function bar(){
  var x = 30;
  function foo(){
    console.log(x) 
  }
  foo();
}   
globleContext: {
  AO:{
    x:10,
    function bar(),
  }
  scope:null
}

bar.[[scope]]=globleContext.AO;

//第二部;
执行bar(); 在globleContext中找到。
进入bar();

barContext:{
  AO:{
    x=30;
    function foo();
  }
  scope:globleContext.AO
}

foo.[[scope]]=barContext.AO;

执行 foo(); 
foo()中没有找到x.去barContext.AO找到了。所以console.log(x);
结果是10。

13. 以下代码输出什么? 写出作用域链的查找过程伪代码

var x = 10;
bar() 
function bar(){
  var x = 30;
  (function (){
    console.log(x)
  })()
}
1、执行bar(),globleContext中有bar()
2 、进入bar()的上下文;
3、执行立即执行函数表达式,但是函数表达式AO中没有找到X,
4、去scope中找,找到的是barContext.AO中,有x的值,得到30.

14. 以下代码输出什么? 写出作用域链查找过程伪代码

var a = 1;

function fn(){
  console.log(a)
  var a = 5
  console.log(a)
  a++
  var a
  fn3()
  fn2()
  console.log(a)

  function fn2(){
    console.log(a)
    a = 20
  }
}

function fn3(){
  console.log(a)
  a = 200
}

fn()
console.log(a)
1、执行fn() 在globleContext中找到了,所以,进入fn()的上下文。
2、console.log(a),当前函数的作用域中有a变量,此时没有赋值//输出 **undefined**
3、再次执行console.log(a),上一行,a已经赋值,所以//输出 **5**
4、a++ ; a=6,不用输出。
5、var a, a仍然等于6.
6、执行fn3() ,当前函数的AO中没有,找到globleContext.AO,有fn3(),进入fn3()的上下文中。
7、console.log(a),当前的AO还没有a,所以,去找到上一级的AO,找到globleContext.AO,然后,得到结果// **1**,顺便,修改了globleContext.AO中的a=200;
8、回到fn(),运行fn2(),找到了fn2(),进入fn2(), console.log(a), 当前AO中没有a,找到上一级也就是fn的AO中,a=6 ,所以输出 ** 6 ** ,顺便修改了fnContext中的AO,是20 。
9、执行fn()中的console.log(a),此时受到第8步骤的影响,所以,输出是**20.**
10 、fn()运行结束,此时,再次运行console.log,受到第7 的影响,a变为了200.所以输出**200**

相关文章

  • 执行上下文、作用域链、this、闭包

    javascript 执行的是词法作用域,即静态作用域。与之相对的是动态作用域。 静态作用域:函数的作用域在函数定...

  • 作用域和作用域链

    作用域和作用域链 作用域 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在Java...

  • 作用域

    何为作用域 任何编程语言都有作用域的概念,简单来说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可...

  • JavaScript中的作用域和作用域链(一)

    作用域 1.作用域的概念: 变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。 2.全局作用域与...

  • JavaScript静态作用域解析

    静态作用域与动态作用域 因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。而与...

  • 词法作用域 - 2023-02-09

    静态作用域与动态作用域 因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。而与...

  • JS基础知识(2) -- 作用域和作用域链

    作用域 作用域就是变量与函数的可访问范围 全局作用域 函数作用域 ES6块级作用域 ES5没有块级作用域,ES6有...

  • 作用域链

    一、作用域 定义:作用域就是变量与函数的可访问范围。作用域控制着变量与函数的可见性和生命周期。 1、全局作用域(G...

  • JavaScript作用域学习笔记

    @(JS技巧)[JavaScript, 作用域] JavaScript作用域学习笔记 概念: 作用域就是变量与函数...

  • 我的JS笔记 -- 作用域

    作用域和作用域链概念 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaSc...

网友评论

      本文标题:函数与作用域

      本文链接:https://www.haomeiwen.com/subject/cnusqxtx.html