精华内容
下载资源
问答
  • 作用域面试题

    2019-12-26 18:42:47
    <!DOCTYPE html> <html lang="en"> <head> ...meta charset="UTF-8">...04_作用域_面试题</title> </head> <body> <script type="text/javascript"> var ...
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>04_作用域_面试题</title>
    </head>
    <body>
    <script type="text/javascript">
      var x = 10;
      function fn() {
        console.log(x);
      }
      function show(f) {
        var x = 20;
        f();      //10
      }
      show(fn);
    
    
    </script>
    </body>
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>04_作用域_面试题2</title>
    </head>
    <body>
    <script type="text/javascript">
      var fn = function () {
        console.log(fn)   
      }
      fn()
    
      var obj = {
        fn2: function () {
         console.log(fn2)     //报错
         //console.log(this.fn2)
        }
      }
      obj.fn2()
    </script>
    </body>
    </html>
    
    展开全文
  • 作用域:浏览器给js的一个生存环境(栈内存)。 作用域链:js中的关键字var和function 都可以提前声明和定义,提前声明和定义的放在我们的内存地址(堆内存)中。然后js从上到下逐行执行,遇到变量就去内存地址查找...

     

    作用域:浏览器给js的一个生存环境(栈内存)。

    作用域链:js中的关键字varfunction 都可以提前声明和定义,提前声明和定义的放在我们的内存地址(堆内存)中。然后js从上到下逐行执行,遇到变量就去内存地址查找是否存在这个变量。有就使用,没有就继续向父级作用域查找直到window下结束,这种查找机制叫作用域链。

    Js代码中存在着大量的变量和函数,我们在使用它们的时候一定要知道它们到底归属谁。

    面试题

    1.

     

     

     

    2.

     

     

    3.

     

    4.

     

    5.

     

    各位看看这些题吧,画图求解就算了

    转载于:https://www.cnblogs.com/yangzhiqiang/p/9891342.html

    展开全文
  • 详细讲了作用域的一些经常会遇到的情况,以及一些面试题;学会用递归处理一些问题

    递归和作用域

    递归:指的就是函数内部直接或间接调用自己;

        function test(){
            test();
        }
    
        test();

    这里值得一说的是递归主要有两个要素

    • 自己调用自己
    • 要有结束条件 (如果只是自己调用自己而没有结束条件,最后会内存泄露,程序崩溃掉);

    递归主要用到的化归思想

    • 化归思想:将一个问题由难化易,由繁化简,把一个困难的问题拆分成很多步来做

    下面来几个用到递归的例子

    例如:

    求前n项和(1 - n)
    
        前5项和: 1 + 2 + 3 + 4 + 54项和 + 54项和: 1 + 2 + 3 + 43项和 + 43项和: 1 + 2 + 32项和 + 32项和: 1 + 21项和 + 21项和: 1                      1
    
        fn(n) = fn(n - 1) + n
        结束条件:
        当n=1的时候直接返回1
    
    
            function sum(n){
    
                if(n == 1){
    
                    return 1;
                }
                return sum(n - 1) + n;
            }
    
            console.log(sum(5));  //15
    

    再例如:

    
    求n的m次方:
    
    求 n的 m次方
    
        求n的5次方: n * n * n * n * n
        求n的4次方: n * n * n * n 
        求n的3次方: n * n * n 
        求n的2次方: n * n 
        求n的1次方: n 
    
        由上面我们可以得出规律: fn(n,m) = fn(n,m-1)*n;
    
        所以申明函数如下:
    
        function pow (n,m){
    
            if(m == 1){
                return n
            }
    
            return pow(n,m-1) * n;
        }

    在斐波那契数列上更实用

    
    1 1 2 3 5 8 13 21 34 55
    
    仔细观察它的规律,我们能得出:fn(n) = fn(n-1) + fn(n-2);
    
    当n是1或者n是2的时候都可以直接return 1
    
    
    function fib (n){
    
        if(n == 1 || n == 2){
            return 1;
        }
        return fib(n - 1) + fn( n - 2) 
    }
    

    递归实现通过id名获取元素原理

        // 获取一个元素的后代元素
        function getChildren (ele){
            var list = [];
            var children = ele.children;
            // 获取到每一个子元素
            for(var i = 0 ; i < children.length; i++ ){
                var child = children[i];
                list.push(child);   
                var temp =  getChildren(child); // 把每一次获取到的子元素保存起来;
               list = list.concat(temp);        // 存到list数组里面去;
            }
    
            return list;
        }
        //通过id名获取到这个元素
        function getElementById(id){
            var list = getChildren(document.body); //找到body下的子元素集合;
            for(var i = 0; i < list.length; i++){
    
                if(list[i].id == id){
    
                    return list[i];
                }
            }
    
            return null;
        }
    
        通过这个两个函数我们就实现通过id名获取元素的原理了;
     ```
    
     ## 作用域 
    
     ### 作用域:顾名思义,变量起作用的范围,就是变量的作用域
    
     * 在js当中有且只有函数可以创建作用域;
     * 块级作用域 (通过代码块限定的作用域)(js中没有块级作用域)
     * 变量的作用域只和函数的声明位置有关系,和函数的具体调用没任何关系,这种作用域就是:词法作用域(静态作用域),而js中的作用域就是这种作用域;
    
    ```js
    
    var num = 123;
    
    function f1 (){
    
        console.log(num);
     }
    
     function f2 (){
    
         var num = 456;
         f1();
     }
    
     f2(); // 123 因为js是静态作用域
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    js作用域中的变量提升 (hoisting)

    在js代码的与解析阶段,系统会将代码中所有的变量声明以及函数声明提升到其所在的作用域的最顶上!

            func();  // 123 
            function func(){
                var num = 123;
                console.log(123);
            }
    
    
    
    
            var a; 
            console.log(a);   // a函数代码块
             a = 1;
            function a (){
                console.log(123);
            }
    
            a();  // a is not a function (a已经被赋值为1了)
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    js作用域变量提升六种特别情况

    1. 函数同名的情况:同名的函数都会被提升,但是后面的函数声明会将前面的函数声明给覆盖掉

    
        func(); // 第二个func
    
        function func(){
            console.log("第一个func");
        }
    
        function func(){
            console.log("第二个func");
        }
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    2. 变量和函数同名的情况:只提升函数,忽略掉变量声明

    
    console.log(typeof a);
    
            console.log(typeof a); // function
    
            var a = 123;
            function a(){
                console.log("我是一个函数");
            }
    
            // 提升后的代码
            var a;
            function a(){
                console.log("我是一个函数");
            }
            console.log(a);
            a = 123;
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    3. 预解析是分作用域的

    
     //   console.log(f); // 会报错 f is not defined
    
        function func(){
    
            console.log(f);
    
            function f(){
                console.log("我是在局部作用域中声明的函数");
            }
        }
        func(); // f函数代码块
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    4. 预解析是分段的 “段”指的script标签

    
        func(); //  我是第一个script标签中的函数 (本script标签中有,则不会去后面的              script标签中)
    
        function func(){
            console.log("我是第一个script标签中的函数");
        }
    
        var b = 10; // 本script标签中没有b,则会去下个script标签中找
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    5.条件式函数声明(不推荐使用) 在条件判断语句中声明的函数,可以将其当做是一个函数表达式来处理,只提升函数名,函数体不会被提升!

        console.log(func);
        if(false){
            function func(){
            }
        }
    
        //相当于做下面的代码处理
        console.log(func);
        if(false){
            var func = function(){};
        }
    
        //  一般情况下 我们遇到一个函数名因为两种原因要实现两种功能时,可以做如下处理
    
        var isDog = true;
        var bark = null;
        if(isDog){
            bark = function (){
                console.log("汪汪汪");
            }
        }else{
            bark = function (){
                console.log("喵喵喵");
            }
        }
        bark();
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    6. 函数中存在形参和变量或者函数同名的时候的提升情况,函数中形参的声明和赋值过程优先于变量提升,并且不参与变量提升

        function test(a){  //参数a就相当于 var a = 100,但是不参与变量提升
    
            console.log(typeof a); // 因为参数a不参与变量提升 所以是function类型
            function a(){
    
            }
        }
    
        test(100);
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    

    最后又是我们的面试题环节了 @_@ ,下面的面试题基本都在上面六种情况内,我就只写答案,不做分析了哈~!

    1.
        function foo() {
            var num = 123;
            console.log(num); //
        }
        foo();    //   123
        console.log(num); // 报错
    
    
    
    2.
    
        var scope = "global";
        function foo() {
            console.log(scope);     // undefined
            var scope = "local";
            console.log(scope);     // "local"
        }
    
        foo();
    
    
    
     3.  
    
        if("a" in window){
             var a = 10;
        }
        alert(a); //    10
    
    
    
    4. 
    
        if(!"a" in window){
             var a = 10;
        }
        alert(a); // ?   undefined
    
    
    5. 
    
        var foo = 1;
        function bar() {
    
            if(!foo) {
                var foo = 10;
            }
            alert(foo);    // 10
        }
        bar();
    
    
    6.
        var num = 123;
    
        function f1() {
            console.log(num);
        }
    
        function f2() {
            var num = 456;
            f1();
        }
        f2();  // 123 
    
    
    
    7.
    
        var num = 123;
        function f1(num) { // 参数理解为:函数内部的一个变量
            console.log(num); 
        }
    
    
        function f2() {
            var num = 456;
            f1(num); 
        }
    
        f2();  // 456
    
    
    
    8. 
    
        var num = 123
    
    
        function f1() {
            console.log(num);
        }
    
        f2();   // 456
    
    
        function f2() {
            num = 456;  // 提升为全局变量,num被修改为456
            f1();
        }
    
        console.log(num);   // 456
    
    
    
    9.
    
        (function (a) {
    
            console.log(a);    // a函数代码块
            var a = 10;
            function a(){}
        }( 100 )); 
    
    
    
    
    10.  这个因为涉及到原型和对象,可能会有点难,但也不是太难,我们一步一步分析就能解决它;
    
            function Foo() {
                 getName = function(){ alert(1); };
                return this;
            }
    
            Foo.getName = function() { alert(2); };
            Foo.prototype.getName = function(){ alert(3); };
    
            var getName = function() { alert(4); };
            function getName(){ alert(5); }
    
    
            Foo.getName(); //  2 
            getName(); //    4
    
            //这个我们要分析一下了:由于变量提升,var getName变量会被函数getName覆盖, 但是后面getName又被赋值了一个函数 
    
            /*
                 var getName = function() { alert(4); };
                function getName(){ alert(5); }
    
                上面代码在作用域解析的时候可以看成下面这样:
                  var getName;
                  function getName(){ alert(5); }
                  getName = function() { alert(4); };
                  所以最后还是 alert(4)的那个函数 这个时候答案就很明显了
            */
    
            Foo().getName(); // ?  1
            // Foo()函数执行的时候  getName = function(){ alert(1); }; getName函数就被赋值成alert(1)的函数了
            // Foo()的返回值是this,指的window, window.getName() = getName()  所以答案是1
    
            getName(); // ?  还是1
    
            new Foo.getName(); // 2  ? 不要管new出来什么对象,Foo.getName被alert(2)的函数赋值了 因为始终会执行,答案是2
    
            new Foo().getName(); // 3    ? new出来的对象没有.getName属性因此会顺着原型链往上级找,所以是3
    
            new new Foo().getName(); // 3   跟上面是一个道理 还是3

    函数可以创建作用域,函数中又可以声明函数,这样就形成了作用域嵌套作用域的链式结构

    • 首先在当前使用这个变量的作用域中进行查找,如果有该变量(有声明),就直接使用当前作用域中的这个变量,但是如果没有
    • 就去上一级作用域中进行查找,如果有该变量(有声明),就直接使用当前作用域中的这个变量,但是如果没有
    • 就继续沿着作用域链向上查找,直到找到全局为止
    
    ## 最后又是我们的面试题环节了 @_@ ,下面的面试题基本都在上面六种情况内,我就只写答案,不做分析了哈~!
    
    ```js
    1.
        function foo() {
            var num = 123;
            console.log(num); //
        }
        foo();    //   123
        console.log(num); // 报错
    
    
    
    2.
    
        var scope = "global";
        function foo() {
            console.log(scope);     // undefined
            var scope = "local";
            console.log(scope);     // "local"
        }
    
        foo();
    
    
    
     3.  
    
        if("a" in window){
             var a = 10;
        }
        alert(a); //    10
    
    
    
    4. 
    
        if(!"a" in window){
             var a = 10;
        }
        alert(a); // ?   undefined
    
    
    5. 
    
        var foo = 1;
        function bar() {
    
            if(!foo) {
                var foo = 10;
            }
            alert(foo);    // 10
        }
        bar();
    
    
    6.
        var num = 123;
    
        function f1() {
            console.log(num);
        }
    
        function f2() {
            var num = 456;
            f1();
        }
        f2();  // 123 
    
    
    
    7.
    
        var num = 123;
        function f1(num) { // 参数理解为:函数内部的一个变量
            console.log(num); 
        }
    
    
        function f2() {
            var num = 456;
            f1(num); 
        }
    
        f2();  // 456
    
    
    
    8. 
    
        var num = 123
    
    
        function f1() {
            console.log(num);
        }
    
        f2();   // 456
    
    
        function f2() {
            num = 456;  // 提升为全局变量,num被修改为456
            f1();
        }
    
        console.log(num);   // 456
    
    
    
    9.
    
        (function (a) {
    
            console.log(a);    // a函数代码块
            var a = 10;
            function a(){}
        }( 100 )); 
    
    
    
    
    10.  这个因为涉及到原型和对象,可能会有点难,但也不是太难,我们一步一步分析就能解决它;
    
            function Foo() {
                 getName = function(){ alert(1); };
                return this;
            }
    
            Foo.getName = function() { alert(2); };
            Foo.prototype.getName = function(){ alert(3); };
    
            var getName = function() { alert(4); };
            function getName(){ alert(5); }
    
    
            Foo.getName(); //  2 
            getName(); //    4
    
            //这个我们要分析一下了:由于变量提升,var getName变量会被函数getName覆盖, 但是后面getName又被赋值了一个函数 
    
            /*
                 var getName = function() { alert(4); };
                function getName(){ alert(5); }
    
                上面代码在作用域解析的时候可以看成下面这样:
                  var getName;
                  function getName(){ alert(5); }
                  getName = function() { alert(4); };
                  所以最后还是 alert(4)的那个函数 这个时候答案就很明显了
            */
    
            Foo().getName(); // ?  1
            // Foo()函数执行的时候  getName = function(){ alert(1); }; getName函数就被赋值成alert(1)的函数了
            // Foo()的返回值是this,指的window, window.getName() = getName()  所以答案是1
    
            getName(); // ?  还是1
    
            new Foo.getName(); // 2  ? 不要管new出来什么对象,Foo.getName被alert(2)的函数赋值了 因为始终会执行,答案是2
    
            new Foo().getName(); // 3    ? new出来的对象没有.getName属性因此会顺着原型链往上级找,所以是3
    
            new new Foo().getName(); // 3   跟上面是一个道理 还是3

    函数可以创建作用域,函数中又可以声明函数,这样就形成了作用域嵌套作用域的链式结构

    • 首先在当前使用这个变量的作用域中进行查找,如果有该变量(有声明),就直接使用当前作用域中的这个变量,但是如果没有
    • 就去上一级作用域中进行查找,如果有该变量(有声明),就直接使用当前作用域中的这个变量,但是如果没有
    • 就继续沿着作用域链向上查找,直到找到全局为止
    展开全文
  • js 作用域面试题

    2020-07-16 23:11:23
    function fn() { console.log(x) } } 乍一看结果就是20,但结果其实是10 每个函数都有自己独立的执行环境,在代码完成的时候就确定了自己的作用域。卡住你的点就在于show函数的形参是一个函数,fn函数传...
    • 下列代码块输出什么
    var x = 10;
    function fn() {
        console.log(x)
    }
    function show(f) {
        var x= 20;
        f();
    }
    show(fn);
    

    用自己的话来说清楚:

    1. 调用show函数,并把fn作为参数传入show函数
    2. 此时好像变成了
    		function show(f) {
    		    var x= 20;
    		    function fn() {
    		    console.log(x)
    		  }
    		}
    
    1. 乍一看结果就是20,但结果其实是10
    2. 每个函数都有自己独立的执行环境,在代码完成的时候就确定了自己的作用域。卡住你的点就在于show函数的形参是一个函数,fn函数传进去的话好像变成了show函数的一个子函数了,其实不是的,你可以理解成就是请fn来帮忙,那fn还是以自己的风格来做事。虽然fn被show调用了,但还是在自己的执行环境里面行动的。
    • 下面代码输出什么
    		var fn = function () {
                console.log(fn)
            }
            fn();
            var obj = {
                fn2:function () {
                    console.log(fn2);
                }
            }
            obj.fn2();
    
    1. 函数fn()输出什么
      1.1 fn既是一个变量,也是一个函数,它是一个函数,函数的语句就是输出fn这个函数,注意这里不是调用自己,而是输出自己,所以只要输出自己就好了。
    2. obj.fn2()输出什么
      2.1 fn2是对象obj种的一个属性,只是这个属性是个函数而已。
      2.2 fn2这个函数就确定了自己的执行环境,函数内部的作用域链包括函数fn2中和全局,都没有fn2这个东西,所以会报错
      2.3 为什么不在对象obj中找
      如果要在obj中找的话要加关键字this。
    • 下列代码输出什么
    function fn(a) {
        console.log(a);     // function a() {alert(1)}
        var a = 2;
        function a() {alert(1)}
        console.log(a);     //2
    }
    fn(1);
    
    1. 问题
      1.1 预解析
      执行函数前,会对函数中的关键字var和function进行预解析
      就是对变量和函数的声明提前,此时不会给变量赋值,当函数与变量同名时,函数会覆盖掉变量;待变量执行了之后,那个名字才会代表变量。
    • 超经典闭包面试题A
    for(var i = 0;i < 5;i++){
    	setTimeout(function (){
    		console.log(i++);
    	},4000)
    }
    console.log(i);
    
    1. 包含的知识点
      1.1 闭包
      1.2 事件循环(event loop)
      1.3 回调函数
    2. 执行逻辑
      2.1 执行代码前先创建全局执行环境
      2.2 在全局执行环境里先执行for循环,for循环会执行5次,每次都会执行setTimeout函数,执行一次setTimeout就需要等待4秒。由于JavaScript是单线程的,只有一个执行栈,如果每次都要等的话是很不好的,所以会先把setTimeout函数先放进一个任务队列中,等到执行栈中执行完了之后再完成任务队列中的任务。
      2.3 for循环执行完了之后i=5,然后就是执行栈中的console.log(i),输出的结果是9,最后执行栈中执行完了之后再执行5个setTimeout函数则最终得到的结果是5,5,6,7,8,9
    3. 问题
      3.1 console.log(i)处于全局执行环境,为什么可以得到for中的i?
      for循环并不是一个函数,所以没有函数作用域。
      var声明的变量不存在块级作用域,之前碰到的看起来好像存在是由于函数作用域的效果。let声明的变量就有块级作用域了。
      因此for循环中声明的i也是属于全局执行环境中的。
    • 将上面的题进行修改B
    for(var i = 0;i < 5;i++){
                (function (x) {
                    setTimeout(function (){
                        console.log(x++);
                    },4000)
                })(i);
            }
    
    1. 问题
      1.1 为什么要修改
      代码的本意就是为了在每一次循环的时候输出对应的i值,而前面那个并不是我们想要的效果
      1.2 前面那段代码为什么不能得到想要的效果而这段代码就可以?
      这段代码中的for循环里面的函数是立即执行函数,每一次都会创建立即执行函数执行环境得到对应的结果。而上面那段并不是立即执行,每次会把执行放入任务队列中的。
      1.3 跟闭包有什么关系?
      闭包的含义就是说函数可以访问到自己的执行环境中访问不到的变量。
      A中setTimeout里面的函数访问不到对应的i
      B中加入了立即执行函数就可以访问到想访问的i了
    展开全文
  • js作用域面试题大全

    2019-09-30 17:22:12
    什么是作用域:浏览器给js的生存环境叫作用域。 什么是变量提升: Js代码执行前,浏览器会给一个全局作用域window Window分两个模块一个是存储模块一个是执行模块 存储模块找到所有的var和f...
  • js作用域面试题

    2019-01-15 17:23:26
    function fn() { var i = 10; return function (n){ console.log(n + (++i)); } } var f = fn(); f(10);//21 f(20);//32 fn()(10);//21 fn()(20);//31  
  • 函数作用域面试题

    2018-12-03 08:06:00
    杨昊2018/12/38:04:131、 vara=123; functionfun(){ alert(a) //123 } fun()2、 vara=123; functionfun(){ alert(a); //undefined a=456; } fun() alert() //1233、 vara=123;...
  • JS作用域面试题总结

    2016-06-01 16:41:00
    关于JS作用域问题,是面试的时候面试官乐此不疲的面试题,有时候确实是令人抓狂,今天看到一个讲解这个问题的视频,明白了那些所谓的“原理”顿时有种豁然开朗的感觉~~~ 1.js作用域(全局变量,局部变量)内部...
  • JavaScript作用域面试题

    2017-11-23 14:20:34
    //执行到fun()函数后,进入局部作用域 //预解析 //找var function 和参数 //找到了var 会把var提前 // num //从上到下一行一行执行代码 var num ; function fun () { var num ; console . ...
  • let arr = [10.18, 0, 10, 25, 23]; arr = arr.map(parseInt); console.log(arr);//[10,NaN,2,2,11] 分析: parseInt首先把第一项转换为字符串,然后看做X(2~36)进制,最后转换为十... 本特别要注意作用域作用域

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,651
精华内容 1,060
关键字:

作用域面试题