zhuhuiwen Front-end Dev Engineer

js面向对象第三天

2016-11-27

11/27/2016 10:42:12 PM

复习

  1. 面向对象编程的案例
    1. 面向对象编程的优势:可以避免全局变量污染,使代码结构更加清晰,便于维护
  2. 创建对象的方式
    1. 字面量 内置构造函数 自定义构造函数
  3. 构造函数
  4. 原型
    1. 对象的原型就是在创建对象的时候,构造函数的原型对象
  5. 继承
    1. 混入式继承(for-in)
    2. 原型继承
      1. 使用混入的方式为原型对象添加成员
      2. 代码

         for(var k in parent){
                         Child.prototype[k] = parent[k];
          }
        
    3. 直接替换原型对象
      1. Child.prototype = parent;
  6. constructor
    1. 原型对象中的属性,指向跟原型相关的构造函数
  7. 当构造函数没有参数的时候,创建对象时后面的小括号可以省略
    1. 代码

        var p1 = new Person;
        console.log(p1);
      
  8. 原型链
    1. 对象都有原型,原型对象也是对象,
    2. 所以原型对象也有原型对象,
    3. 这样就形成一个连式结构,叫做原型链
  9. instanceof
  10. Object.prototype
    1. constructor
    2. hasOwnProperty(“属性名”)
    3. isPrototypeOf(对象)
    4. PropertyIsEnumerable()
    5. toString toLocaleString
    6. valueOf
    7. proto

经典继承

  1. Object.create()
  2. 创建出来一个obj对象,原型对象为obj1
  3. 这是ECMA5中新增的,会存在兼容性问题
  4. 经典继承的兼容性处理
    1. 1.浏览器能力检测
    2. 如果浏览器支持这个方法,就直接使用
    3. 如果浏览器不支持,
    4. 代码封装

           //第一种: 这样会出现对全局的设置...管理混乱
           Object.prototype.create = function () {}
      	
      			
      	
           要实现原型继承,就得找到原型,找原型的方式有两种
           1.构造函数去找
               所以要用构造函数,所以首先需要创建一个构造函数
               function F(){}
               F.prototype = obj1;
               var obj = new F();
           2.对象去找
               对象去找有兼容性问题,所以不用它
               自己实现 创建一个对象继承自另外一个对象(原型继承,新的对象的原型需要变成obj1)
                var obj = {};
                obj.__proto__ = obj1;
      
  5. 封装的自己实现原型继承的函数
    1. 参数:需要继承的对象(父对象)
    2. 返回值:新创建的对象(子对象)
  6. 完整分析代码

     <script>
         var parentObj = {
             name :'waxun',
             age : 11,
             sayHi : function(){
                 console.log('-----');
             }
         };
         //将parentObj的地址复制了一份给childObj1
         var childObj1 = parentObj;
         //将parentObj的内容作为childObj2的原型给了其子元素
         //这种方法存在兼容性问题: ecma6 解决办法
         var childObj2 = Object.create(parentObj);
         /* 3.isPrototypeOf 方法
          *   对象名.isPrototypeOf(对象1)
          *   功能:判断对象是不是对象1的原型对象
          * */
         console.log(parentObj.isPrototypeOf(childObj2));//true
    	
         /*
         * 解决Object.create()的兼容性问题
         * 1. 能力检测
         *
         * */
         /*if(Object.create){
             //如果支持的话,就将父级作为子集的原型存在
             var childObj3 = Object.create(parentObj);
         }else{
             //如果不支持
             //第一种方法:
             //  直接将父级对象给自己对象的__proto__,但是__proto__又存在兼容性问题,不合适
             //  这里是一个是一个普通的对象,所以不好通过prototype进行设置,可以,但是给了全局
             // 第二种方法:
             //  需要一个构造函数来产生一个实例,就是子元素
             // 这个构造函数的原型是父级的对象,new 出来的子元素就也有
    	
             //var childObj3.__proto__ = parentObj;
             function Fn(){};
             Fn.prototype = parentObj;
             var childObj3 = new Fn();
         }*/
    	
    	
         function myCreate(parent){
             if(Object.create){
                 return Object.create(parent);
             }else{
                 function Fn(){};
                 Fn.prototype = parent;
                 return (new Fn());
             }
         }
         var childObj4 = myCreate(parentObj);
     </script>
    

静态方法和实例方法

  1. 静态方法
    1. 通过构造函数去访问的方法就是静态方法
  2. 实例方法
    1. 通过实例去访问的方法就是实例方法
  3. 代码

     function Person(){
         this.sayHi = function(){
             console.log('hi----');
         }
     };
     Person.sayHe = function () {
         console.log('sayHe');
     };
     Person.sayHe();//sayHe
    
     var  p = new Person();//hi----
     p.sayHi();
    

Function

  1. 创建函数的方式
      1. 函数声明
    1. 函数表达式
    2. new Function()
  2. Function
    1. 使用 new Function() 创建空函数
    2. 使用 new Function(methodBody) 创建一个具有函数体的函数
    3. 使用new Function(arg1,arg2,arg3,arg4,arg5….MethodBody) 创建一个具有参数和函数体的函数
      1. agr1…argn为 函数的形参名 字符串类型
  3. Function代码案例

     //1.使用 new Function()  创建空函数
     var func = new Function();
     func();
     // 2.使用 new Function(methodBody)  创建一个具有函数体的函数
    
     var func2 = new Function('console.log("hihi")');
     func2();//hihi
    
     //3.使用new Function(arg1,arg2,arg3,arg4,arg5....MethodBody) 创建一个具有参数和函数体的函数
     //求两个数的和
     var fun3 = new Function('num1','num2','return num1+num2');
     console.log(fun3(1, 2));//3
    
  4. Function 创建函数的
    1. 能够将字符串转换成代码!!!
  5. 如何处理方法体代码过长的问题
    1. 字符串拼接
    2. 模板—比较好用
    3. 反引号
  6. 代码

     <script type="text/html" id="tpl">
         var sum = 0;
         for(var i = n;i < m;i++){
             if(i%2 == 0){
             sum+=i;
             }
         }
         return sum;
     </script>
     //通过模板进行获取字符串
     var tpl = document.getElementById('tpl');
     var str = tpl.innerHTML;
     //console.log(str);
     var fn  = new Function('n','m',str);
     console.log(fn(1, 100));
    

eval

  1. eval可以将字符串转换成代码,并且立即执行
  2. 代码

     eval("var a = 10;");
     console.log(a);
    
  3. Function 和 eval 区别
    1. Function是用来创建函数的,虽然也可以将字符串转换成代码,但需要掉用函数才能执行
    2. 会直接将字符串转换成代码并执行!!
    3. 都存在
      1. 效率问题
      2. 安全性问题
  4. 例子: 计算器
    1. res.innerText = eval(num1 + operator + num2);

Function和Object的关系

  1. 代码

     //Function---->Function.prototype---->Object.prototype----->null
     console.log(Function instanceof Object);
     console.log(Function instanceof Function);
     //Object---->Function.prototype---->Object.prototype----->null
     console.log(Object instanceof Object);
     console.log(Object instanceof Function);
    

arguments

  1. 在定义函数的时候,如果有写形参,在调用的时候,实参的个数,可以和形参个数不对应
  2. arguments 伪数组
    1. 在函数内部的一个对象
    2. 在函数调用的时候,会将所有传入的实参,依次存入该对象
    3. 在实参个数不确定的情况下,就可以使用arguments对象来获取传入的实参
    4. 不论有没有形参,在函数调用的时候,都会将传入的实参存入arguments对象
  3. 代码案例

     function test(){
         for(var i = 0 ;i<arguments.length;i++){
             console.log(arguments[i]);
         }
     }
     test();
     test(1,2,3);//打印1 2 3
    
  4. arguments对象的
    1. length属性可以用来表示 用户传入的实参的个数
  5. callee:
    1. 指向当前arguments对象所在的函数
    2. 在匿名函数中实现递归
  6. 代码

     function test(){
         console.log(arguments.length);//0 实参的长度
         console.log(arguments.callee);//指向当前arguments对象所在的函数,打印当前的函数的声明了
     }
     test();
    
     //在匿名函数中实现递归
     (function(){
         //因为会找函数自身
         arguments.callee();
     })();
    

函数的属性

  1. name是函数的函数名
  2. length属性是函数的形参的个数
  3. caller 指的就是函数的调用环境,
    1. 如果是全局的调用,caller就是null,
    2. 如果在其他的函数中,那这个caller就是外层的函数
  4. 代码

     function test1(a,c,d){
         console.log(test1.caller);
     }
     //test1();//null
    
     function test2(){
         test1();
     }
    
     test2();//现在打印的是test2的函数的声明,符合外层的定义
    
     console.log(test1.length);//3*/
    	
     /*这样去找父级是谁就方便了*/
     function Person(){}
     var p = new Person();
     //去找出p对象的构造函数,就是其父级是谁
     console.log(p.constructor.name);//Person
     console.log(p.__proto__.constructor.name);//Person
    

11/28/2016 1:27:00 AM


Similar Posts

Comments