zhuhuiwen Front-end Dev Engineer

js面向对象第四天

2016-11-29

11/29/2016 8:33:26 AM

面向对象总复习

面向对象的基本概念

三大特征

的方式

自定义构造函数

原型的基本概念以及使用方式

原型链

继承的实现方式

Function

eval

Function的原型链

完整的原型链

Object.prototype的成员

arguments

使用new Function创建出来的函数,函数名.name 为 anonymous 使用var func = function(){} 创建出来的函数,函数名为:func function Person(){}

函数名的扩展

  1. var func = function(){};
  2. var func = function Test(){};
    1. 在test里面可以使用

基础复习 面型对象 高级讲义 ————————————-

递归

  1. 在函数是内部直接或者间接的调用自己
  2. 如果没有结束条件,那么递归就是一个死递归
  3. 递归的两个要素
    1. 自己调用自己
    2. 要有结束条件
  4. 化归思想
    1. 将问题由难化易,有繁化简的过程,是转化和归结 11/29/2016 10:33:44 AM

      递归练习

  5. 阶乘 求n的阶乘 ## ##
  6. 函数里面的变量进行返回,外面可以接收
  7. 打印的空数组是什么????
  8. 递归应用
  9. 实现getElementbyId
    1. 自己实现
      1. 还是获取所有的元素
      2. 面试题 11/29/2016 11:39:23 AM

11/29/2016 2:27:18 PM

作用域以及词法作用域

  1. 指的就是
    1. 变量其作用的范围
  2. js中有且只有函数可以创建作用域
  3. 词法
    1. 一旦代码写好,就可以从代码结构分析出来,变量的作用
  4. 动态作用域(js中没有)
    1. 今天作用域和动态
    2. 如果是词法作用域,那么直接按照语法分析,test1访问的是num应该是全局的
    3. 如果是动态语法作用域,那么久按照自己的运行环境进行分析,就是自己函数里面调用的num
  5. 块级作用域
    1. 代码块
      1. {}
      2. (js中没有块级作用域)
  6. 小题目

变量提示

  1. js执行分两个阶段

  2. 预解析
      1. 将函数声明,以及变量的声明提示到其所在作用域的最顶上
    1. 注意:
      1. 函数声明会被提示
      2. 函数表达式不会被提示
      3. new Function这种形式创建函数 不能被提示
  3. 执行

    变量提升中的特殊情况处理

  4. 当函数同名的时候,都提示,但是后面的会把前面的覆盖掉
  5. 函数和变量同名
    1. 只会提示函数声明,忽略变量
      1. 是先预解析变量,再函数,—>打印函数
  6. 预解析是分作用域的
  7. 预解析是分段的——–注意: 是预解析分段
    1. js中的变量和函数提升是分段的(script标签)

      代码分段

  8. script标签说明

    条件是函数声明

  9. 条件是函数声明
    1. 在新的版本的浏览器啊中,都不支持
    2. 声明的提升
  10. 在条件里面加个函数

    作用域链

  11. 概念
    1. 函数可以创建作用域,函数中又可以声明函数,这样就形成了作用域套作用….

绘制作用域链图

变量的搜索原则

  1. 当遇到一个变量的使用的时候,先在当前的作用域中去找这个变量,如果找到了就使用
  2. 如果没有找到,就去外层的作用与众进行查找,如果找到了,就直接使用
  3. 如果没有找到,就继续往上查找,直到找到0级
  4. 再找不到就报错

    面试

  5. 声明变量var,如果有同名的全局,就相当于修改
    1. 如果没,则相当于新增了这个全局变量
    2. 不推荐使用
  6. in 关键字
    1. 用来判断是否可以通过对象来访问某个属性
    2. 声明全局变量,就相当于给window添加属性

      面试题

  7. 先做变量提示

    递归

  8. 概念
    1. 在函数内部直接或者间接的调用自己,就是递归
  9. 划归思想
  10. 练习题
    1. 前n项和
    2. n!
    3. m的n
    4. 斐波那契
    5. 使用递归获取所有的后代元素
      1. 理解后敲好多遍

        作用域

  11. 变量起作用的范围
  12. js中能且只能创建作用域的东西是函数
  13. 词法作用域
    1. 代码写好的时候根据代码的结构就能确定变量的作用域,—词法
    2. 对应的是动态作用域,js中没有动态作用域
  14. 块级作用域
    1. js中没有
    2. if for switch 代码块中的作用域
  15. 作用域链
    1. 函数可以用来创建作用域,函数中还可以创建函数,所以
  16. 绘制
    1. 画一条直线来表示0级作用域链
    2. 在全局作用域中去参照所有的变量和函数的声明,将其以小方块的形式画在0,作用域上
    3. 在从0级作用域中的函数涌出新的作用域链,再去查找变量和函数
    4. 以此往复,就嫩恶搞滑出整个作用域链
  17. 变量的搜索原则
    1. 现在使用变量的作用域中进行查找,如果找到了就直接使用
    2. 如果没有找到,就去上一级作用域链中进行查找,….
    3. ….
  18. 变量的提升
    1. 预解析阶段
      1. 在预解析阶段,会将所有的变量声明以及函数声明,
      2. 情况
        1. 变量和函数同名
          1. 只函数
          2. 函数和函数同名
        2. 都提升,但是会有覆盖
        3. 变量提示是分段(script)
    2. 执行阶段
  19. 条件是函数声明
    1. 在条件语句中声明的函数,就是
    2. 能否被提… 是浏览器版本的问题…

11/29/2016 6:44:44 PM

11/29/2016 8:52:05 PM

函数名扩展

  1. 函数表达式
    1. 代码

       var func = function(){
           console.log('表达式方式的函数')
       };
       func();//表达式方式的函数,可以直接调用
      
  2. 注意:
    1. 在使用函数表达式创建函数的时候,
    2. 后面表达式是可以有函数名的,但是这个函数名不能直接使用。
    3. 这个函数名,只能在函数内部使用
    4. 代码

       var func2 = function test(){
       //只能在这里面进行调用,是死循环,这个函数
       //02-函数名的扩展.html:18 Uncaught RangeError: Maximum call stack size exceeded(…)
       //test();
       console.log('我是函数表达式2');
       };
       //test();//在外面不可以调用通过函数表达式的函数
       func2();//只能通过自己赋值的名称去调用  我是函数表达式2
      

递归

  1. 在函数内部直接或者间接的调用自己
  2. 如果没有结束条件,那么递归就是一个死递归
  3. 递归的两个要素
    1. 自己调用自己
    2. 要有结束条件
  4. 划归思想
    1. 将问题由难化易,由繁化简的过程,称为化归思想, 是转化和归结的简称
  5. 案例
    1. 代码

       *    前n项和
       *
       *    5 : 5+前四项和    5+getSum(4) = 5+10
       *    4:  4 + 前三项和  4+getSum(3) = 4+6
       *    3: 3 + 前两项的和3+getSum(2) = 3+3
       *    2: 2 +前一项的和  2+getSum(1) = 2+1
       *    1: 1              1
      	
       function getSum(n){
           if(n==1){
               return 1;
           }
           return n+getSum(n-1);
       };
       console.log(getSum(5));
      
  6. 求n的阶乘 n!

     代码
    
         阶乘  求n的阶乘   n!
                  /*
         *阶乘  求n的阶乘   n!
         * 5 : 5 * product(4)
         * 4 : 4 * product(3)
         * 3 : 3 * product(2)
         * 2 : 2 * product(1)
         * 1 : 1
         * */
    	
         function product(n){
             if(n==1){
                 return 1;
             }
             return n*product(n-1);
         };
         console.log(product(3));//6
    
  7. 求m的n次方

         /*
         * 求m的n次方 m , n
         * m : m * m * m *m * m   m的5次方
         * m : m * m * m *m       m的4次方
         * m : m * m * m          m的3次方
         * m : m * m              m的2次方
         * m : m                  m的1次方
         * m : m * 前四项的n-1次方
         * 公式:   m * pow(m,n-1)
         * */
    	
         function pow(m,n){
             if(n==1){
                 return m;
             }
             return m * pow(m,n-1);
         };
         console.log(pow(2,3));//8
    
  8. 斐波那契1 1 2 3 5 8
    1. 代码

           /*
       * 1 1 2 3 5 8
       * 斐波那契
       * 1
       * 1
       * fb(n-1)+fb(n-2)
       * */
       function fb(n){
           if(n==1||n==2){
               return 1;
           }
           return fb(n-1)+fb(n-2);
       }
       console.log(fb(4));//3
      

递归应用

变量提升

  1. js执行分两个阶段
    1. 预解析
      1. 将函数声明,以及变量的声明提升到其所在的作用域的最顶上
    2. 执行
  2. 注意:
    1. 函数声明会被提升
    2. 函数表达式不会被提升
    3. new Function这种形式创建的函数 不能被提升
  3. 代码

     /*1.函数声明会被提升*/
     fn1();//fn1调用
     function fn1(){
         console.log('fn1调用');
     }
    
    /2.函数表达式不会被提升/
     fn2();//08-变量提升.html:19 Uncaught TypeError: fn2 is not a function(…)
     var fn2 = function(){
         console.log('fn2调用');
     }
    
     /*3.new Function这种形式创建的函数 不能被提升*/
     fn3();//Uncaught TypeError: fn3 is not a function
     var fn3 = new Function('console.log("fn3调用")');
    

变量提示中的特殊情况处理

  1. 当函数同名的时候,会都提升,但是后面的会把前面的给覆盖掉!!!
  2. 当函数和变量同名的时候, 只会提升函数声明,忽略变量
  3. 预解析是分作用域的
  4. 代码

     //当函数同名的时候,会都提升,但是后面的会把前面的给覆盖掉!!!
     fn();//fn-----02
     function fn(){
         console.log('fn----01');
     }
     function fn(){
         console.log('fn-----02');
     }
    
    
     //当函数和变量同名的时候, 只会提升函数声明,忽略变量
     /*test();//test()---
     function test(){
         console.log('test()---');
     }
     test = 123;*/
    	
    
     //    预解析是分作用域的
     test();//test()
     var test = 2;
     function test(){
         var num = 10;
         function num(){
         }
         console.log('test()');
     }
     console.log(test);//2
    
     /*分析预解析*/
     //注意:  变量和函数同名字的时候,函数的声明优先,所以变量的var test不在了
     function test(){
         var num = 10;
         function num(){
         }
         console.log('test()');
     }
     test();//'test()'
     test = 2;
     console.log(test);//2
    

预解析是分段的

  1. js中的变量和函数提升是分段(script标签)的
  2. 就是在自己的script中访问不到别的script中的值
  3. 自己的总结注意:
    1. 变量的时候,预解析分段,
      1. 执行不分段,是从上到下执行的,上面有的话,可以进行打印
    2. 函数也是一样的,预解析分段,执行不分段
    3. 没问题,执行是从上到下执行的
  4. 代码

         <script>
     //    fn1();//第一个fn
         function fn1(){
             console.log('第一个fn1');
         }
         //Uncaught ReferenceError: fn2 is not defined(…)
     //    fn2();
     //    console.log(num1);
     </script>
     <script>
         fn1();//第一个fn1
         var num1 = 10;
         fn2();//第二个fn2
         function fn2(){
             console.log('第二个fn2');
         }
     </script>
    

条件式函数声明

  1. 在新的版本的浏览器中,都不支持
  2. 数声明的提升
  3. 自己的理解
    1. 条件满足的情况下
    2. 函数的调用在函数的声明之前是会报错的,因为条件函数不支持函数的声明
    3. 但是变量是支持条件函数中的声明的
  4. 代码

         //test();//Uncaught TypeError: test is not a function(…)
        /* if(true){
             function test(){
                 console.log("我是在if语句中声明的函数");
             }
         }*/
         //我是在if语句中声明的函数
         //test();//如果条件为真,在函数声明的下面,可以进行整除的调用
    	
         console.log(num);//undefined
         if(true){
             var num = 10;
         }
         console.log(num);//10
    
  5. 补充的11/30/2016 1:50:52 PM :
  6. 条件式函数声明
    1. 只会提升函数名!!!不会提升函数体!!!!
  7. 代码案例

         /*代码的执行
         * 条件式函数声明可以进行在外部拿到foo的声明....
         * */
         console.log(foo);//undefined
         if("foo" in window){
             console.log(foo);//foo(){}
             //解析成函数表达式的形式,所以
             // var foo = function(){};
             function foo(){}
         }
    

作用域链

作用域链概念

  1. 概念
    1. 函数可以创造作用域,函数中又可以声明函数,
    2. 这样就形成作用域套作用域的链式结构,称作作用域链
  2. 代码

     function test1(){
         function test2(){
             function test3(){
                    
             }
         }
     }
    

绘制作用域链

  1. 绘制步骤
    1. 先画一条直线,用来表示0级作用域链
    2. 然后在全局作用域中,查找变量以及函数的声明,以小方块的形式,将其画在0级作用于链上
    3. 再从0级作用域链中的函数中引出新的直线,用来表示1级作用域链
    4. 在去对应的函数中查找变量以及函数的声明,以小方块的形式,将其画在1级作用于链上
    5. 再沿着当前作用域一直往里找,找到一个函数画一条线,以此重复,直到找不到函数为止
  2. 例子

变量的搜索原则

  1. 当遇到一个变量的使用的时候,先在当前的作用域中去找这个变量,如果找到了,就直接使用
  2. 如果没有找到,就去外层的作用域中进行查找,如果找到了,就直接使用
  3. 如果没有找到,就继续往上查找,直到查找到0级作用域链

  4. 代码案例

         function f1(){
                 var num =10;
             }
             function f2() {
                 f1();
                 console.log(num);
             }
             f2();//Uncaught ReferenceError: num is not defined(…)
    

面试题

  1. 注意:
    1. (不推荐使用)声明变量如果不使用var关键字,就相当于如果有同名的全局变量,则是修改其值
    2. 如果没有同名的全局变量,则相当于新增了这么一个全局变量
  2. in 关键字 用来判断是否可以通过对象来访问某个属性
  3. 声明全局变量,就相当于给window对象新增了一个属性
  4. 变量声明提升
  5. 代码

                // 01
               /*  var num = 123;
                 function f1() {
                     //去访问的全局变量
                     console.log( num );
                 }
                 function f2() {
                     //去改的全局变量
                     num = 456;
                     f1();
                 }
                 f2();//456*/
    	
    	
         //02
    	
                /* var arr = [];
                 for ( var i = 0; i < 10; i++ ) {
                     arr.push( i );
                 }
    	
                 for ( var i = 0; i < 10; i++ ) {
                     console.log( arr[ i ] );
                 }*/
    	
                 //0-9输出,for循环中的i是同一个,下面使用的时候,将i改了
    	
                /* function foo() {
                     var num = 123;
                     console.log(num); //
                 }
                 foo();//123
                 console.log(num); //num is not defined(…)*/
    	
    	
               /*  var scope = "global";
                 function foo() {
                     //找自己作用域下面的
                     console.log(scope); //undefiend
                     var scope = "local";
                     console.log(scope); //local
                 }
                 foo();
                 //找自己的全局变量
                 console.log(scope);//global*/
    	
         //03
    	
        /* if("a" in window){
             var a = 10;
         }
         alert(a);//10*/
    	
         //变量提升
        /* var a;
         if("a" in window){
             a = 10;
         }
         alert(a);//10*/
    	
         //4
          var foo = 1;
          function bar() {
              //是判断自己变量!undefiend 是true
              if(!foo) {
                 var foo = 10;
              }
             alert(foo); //10
          }
          bar();
    	
         /* 解析过程
          var foo;
          function bar() {
          if(!foo) {
             var foo = 10;
          }
          alert(foo); //10
          }
          foo = 1;
          bar();*/
    	
     //   console.log(!undefined);//true 11/29/2016 11:55:19 PM
    

复杂的面试题目

	<script>
	    /*
	    *分析步骤
	    * 1. 先将函数和变量的预解析进行变化
	    * 2. 划出函数和原型链和全局变量的范围和对应的值
	    * 3. 注意:
	    *       1.Foo().getName();
	    *       2. new的时候,代码的执行顺序
	    * */
	           /* 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); }*/
	
	    /*变量和声明提升后的代码*/
	    function Foo() {
	        getName = function(){ alert(1); };
	        return this;
	    }
	    function getName(){ alert(5); }
	    Foo.getName = function() { alert(2); };
	    Foo.prototype.getName = function(){ alert(3); };
	   getName = function() { alert(4); };
	
	
	   /*最后一个是4,将之前的5给覆盖掉了*/
	   getName(); // 4
	    //Foo()当成普通的函数去调用,getName去修改全局的变成1
	    Foo().getName(); // 1  先执行Foo()当成正常的函数进行调用,返回的是window对象,再进行调用全局的getNmae函数
	    getName(); // 1  访问的是上面函数改过的1
	    new Foo.getName(); // 2,  先调用后面的,是静态函数的方法
	    new Foo().getName(); // 3  先创建一个对象,访问到是原型里面的3
	    new new Foo().getName(); // 3 先执行第二个new创建一个对象,去调用原型链中的方法ok
	</script>

11/30/2016 12:32:14 AM


Similar Posts

Comments