面向对象 [记录]

面向对象 VS 面向过程
  
  过程:流程式写法 - 到哪步该干啥
  对象:所有程序执行都是从对象出发

  [] {} null
var a = new Image() | object()
  对象拥有属性和方法

  啥时候用|好处:(功能|方法)
    01 所有功能都从对象出发以达到一个对象实现某种功能的效果
      (比如JQ都是从对象出发 JS,JQ互不污染)
    02 面向对象可支持扩展(继承)

 

 
var a = new object();
a.name='XXX';
a.show = function(){};

function peo(){return obj;}
peo('xxx')  -->  里面this指window(peo内部)
new peo('xxx')  -->  
    在函数执行前+new
        01 在函数内部自然会产生一个对象并this指向这个对象
        02 函数默认返回产生的对象

this指向
     function a(){alert(this);}
     var k = a();  -->  window  -->  k = undefined
     var k = new a();  -->  obj  -->  k = obj (默认返回)
        // new a() 代码相当于
         // var obj = {};
         // alert(this);
         // return obj;
         // 相当于多了2条 不用写 默认return
     构造函数
         function peo(k){
             this.name = k;
             this.fn = function(){};
         }

 

工厂模式
    (构造函数就是工厂模式 | 工厂=加工东西) = 简化后的构造函数 (默认要有原料 默认要出工厂)
    原料(var obj=new object())  -->  加工(obj.name='xxx')  -->  出厂(return obj)

 

通常构造函数第一个字母大写
    Peo{a=10;}
    obj1.fn == obj2.fn   -->  false    -->   对象所属对象都不一样
        老李家的狗和老王家的狗不一样,obj1和obj2是不同的
    对象的赋值和引用
        obj1.a == obj2.a   -->  true !!!!!

    比较的时候 对象和函数作比较时 不仅仅要内容一样还要存储位置|地址都要一样
    数字,字符串,bool比较 只要内容一样 就好了

    new一个对象就要开辟空间去存储

 

原型
    prototype 不用让一样的东西总是去开辟空间存储
    只有构造函数有原型(一个函数是不是构造函数是看如何调用的 用new去调用的就是)

    Peo.prototype.fn = function(){}  公有写原型中
        此时 obj1.fn == obj2.fn    -->  true !!!!! (公有)
    私有属性写构造函数里,公共属性写prototype里面,原型的方法里面的this指向的是你执行的时候的对象
        谁去执行this就指向谁(obj1执行就指向obj1,obj2执行就指向obj2)

    原型好处:节约内存空间

    但 this.name 不共享
        function Peo(name){this.name = name;}  <-- 私有
        Peo.prototype.fn = function(){}  <-- 公有

 

方法链
    $('#box').css({}).click().animation()     -->   这个就是
    function Peo(name,age){
        this.name = name;
        this.age = age;
    }
    Peo.prototype.fn1 = function(){!!!重点 return this;}
    Peo.prototype.fn2 = function(){!!!重点 return this;}
    p1 = new Peo('xxx',22);
    p1.fn1().fn2();   需要p1.fn1()是一个对象 那么fn1和fn2里面 return this

 

包装对象
    对于非对象的数据类型是由包装对象产生的
    是对象的:
        数组 var arr = new Array();
             var arr = [1,2,3,4];
        arr.push   <--  push 在构造函数原型中(prototype中)
        那么 Array.prototype.push = function(){} 那么push就被重构了,没了
    写类似push的方法
        function(){
            var argu = arguments;
            for (var i = 0; i < argu.length; i++) {
                this[this.length]=argu[i];
            }
        }

    非对象:
        字符串 对象才能.点 | 对象才能.方法
        var str = 'qwer'
        str.charAt(2);  str拥有string函数--包装对象
        string.prototype.charAt = function(){}
        Array 和 String 差别:
            string只有.点方法才出来 之后消失

        +自定义属性 str.number = 10;
            alert(str.number)   -->   undefined
            解释:因为它不是个对象
                去原型prototype找,因为他不是个对象,
                那么去原型找就会产生一个对象(产生一个叫包装对象的东西),number=10,
                和string相关联去访问 string.prototype后对象销毁
            每次产生新的包装对象
            str.number --> 产生对象 number=10  -指向-> string.prototype --> 对象死亡
                number 不是string的  |  执行完包装对象立马死亡
            alert(str.number)
                str.number --> 产生对象(包装对象)  --> string.prototype
            这里两个包装对象不相等
            给非对象.点number(不存在)
                 --> 就会产生一个包装对象来执行.点操作
                 --> 操作完之后对象立马死亡
                 --> alert又会产生一个包装对象
                 --> 此时你给上一个包装对象赋值,这个对象拿不到赋值,2个对象不一样
                     上一个对象死亡,用完一次死一次,临时的

 

原型链 _proto_
    对象和他的构造函数的关系
    构造函数a(它是有原型链的a.prototype) -->  创建出对象objA对象
        说的是 a.prototype 和 objA 之间的关系
    function A(n){this.n=5;}
    A.prototype.n=10;  (!!! A.prototype 是个对象 )
    此时 alert(a1.n)   =  5
    按原型链去找 
     --> 自己有n属性吗?有 有了之后就不会再去找
     --> 没有则就去构造函数找
     --> A.prototype 是个对象 对象有构造函数(假设B) -- 构造函数有原型

     [A]构造函数 ---创建出(new)---> objA
      | [A]有原型
     [A.prototype] *** 和objA有关系 ***
                   | [A.prototype]是个对象能.点
                  | 是对象就有构造函数 假设B
                [B]
                 | 
                [B.prototype]  *** 和 A.prototype有关系 ***
                 | 
                [...]
                 | 
                [object] 一直到祖宗 到根
                 | 
                [object.prototype]

    往下找 一直找到obj都没有则 undefined

    如:object.prototype.number = 10;
        objA  --> A.prototype --> B.prototype --> ...  --> object.prototype

 

原型链默认属性
    对象原型里面本来就有默认的属性和方法
    hasOwnProperty是不是对象自己的属性 返回bool
        在原型里的则false
        在A(){里面} 它自己本身(即私有的)
        如:arr   push:false | length: true
    constructor 属性:值是构造函数
        当一个new一个对象的时候,原型默认带有
    instanceof 判断构造函数是否一样

    function A(){}
    方法一:(正确)
    A.prototype.n = 10;
    A.prototype.fn = function(){}
    方法二:
    A.prototype = {
        n: 10,
        fn = function(){}
    }
    1和2一样的 但是2这么写把原型默认属性覆盖了
    new OA 
        OA.hasOwnProperty 是不是对象私有属性
        OA.constructor 相当于 A.prototype.constructor = A 弹出它的原型
        instanceof 判断对象1的构造函数是不是构造函数1
            对象 instanceof 对象
            OA instanceof A

 

继承
    儿子继承父亲,用父亲的方法和属性 儿子的改变不会影响父亲
    call继承私有属性
    function Peo(n){this.n=n;}
    Peo.prototype.fn1 = function(){alert(this.n);}
    function PeoAge(n,a){this.a=a;} 通过继承创建一个子类

    现在不知道peo里面所有属性 但是我要继承
    function PeoAge(n,a){
        Peo.call(this,n);(继承|改变了this的指向)
        或者把Peo执行一遍 Peo.call(n)
        一执行PeoAge就执行了
        this.a=a;}
    Peo(a1,a2,a3) 拓展成 PeoChild(a1,a2,a3,b1) 多了个b1 
         --> 则把Peo执行一遍 改变了this的指向
         --> 抛开一切执行 Peo() this指向window 没有new 自己去找行为window
         --> this指向改为自己的this 那么Peo.call(this) 
              那么Peo里的this指向此时call里面的this
              此时的this为op(创建出来的对象)

              var op = new PeoChild(a1,a2,a3,b1) op因为返回的就是this
              Peo.call(this,+参数(a1,a2,a3))
                        this,a1,a2,a3

              或 var op = new PeoChild([a1,a2,a3],b1)  [这里是父亲要的参数]
              Peo.call 改为 Peo.apply(this,arr);

              call参数要一个个摆着
              apply 参数只要一个数组(放数组里)


    要把父亲的原型也继承下来
    那么 PeoChild.prototype = Peo.prototype [X] 错误!!!
        = 为引用  引用关系
        儿子的改变不影响父亲 此时 PeoChild.prototype.fn2 = ... 就会影响父亲原型
        两边都是对象 = 的时候就是引用 一旦引用 子新增父也会跟着改
    那么直接= 为引用 选择不直接=

        第一种Clone:
            构建个新的对象 把一个对象完全克隆
            PeoChild.prototype = new clone(Peo.prototype)
        第二种继承:
            PeoChild.prototype(对象) = Peo.prototype(原型)
            对象本身的属性改变能否改变或影响其构造函数原型属性的改变  ----  不会!!!
            var a = new Peo()  a.x=5;
            a.fn 也能读取原型属性
            那么 
             --> 中间介质 function Fn(){}
             --> Fn.prototype = Peo.prototype
             --> PeoChild.prototype = new Fn();
             --> 自身无找原型 var obj = new PeoChild();
             --> obj.showName();
             --> showName:PeoChild无 找原型 PeoChild.prototype(他是Fn) 无 把Fn它是 Peo.prototype



    Clone:
        对象克隆
        var a={aa:10,bb:20,cc:30}
        现在要b拥有a所有属性 但b改变不影响a
        var b=clone(a)
        function clone(obj){
            代码可以改成new clone
            前后去掉即可 + 改this     
            var newObj=new object()/={};
            for (var k in obj) {
                newObj[k]=obj[k]; 这句全是引用,赋值
            }
            return newObj;
        }
        此时 bb.dd=50 alert(a.dd) ----- undefined 不影响了
        那么此时a里面有个 qqq:{a:'a',b:'b'} 对象
        .clone之后 b.qqq.c='c'   alert(a.qqq.c)  会弹出c!!!!
        clone里面循环一旦读到qqq是一个对象
        那么右边是对象了 又变成引用了 不是赋值
        要保证 = 是赋值 不管多少层下去
        那么只要是个对象就要进行克隆
        function clone(obj){    
            for (var k in obj) {
                this[k]=obj[k];     obj[k]!!!要进行递归  遇到对象就要进行克隆
            }
            for改为
            for (var k in obj) {
                if(typeof obj[k] == 'object'){
                    this[k]=clone(obj[k]);
                }
                this[k]=obj[k];
            }
        }

    递归:
        4!=4*3*2*1
        拆分为 4!=4*3!  3!=3*2! 2!=2*1! ... 递   ----  归:到某一点归
        x==1 的时候直接返回1
        function f(x){
            if(x==1){return 1;}
            return x*f(x-1);
        }
    Clone fn:
        function clone(obj){    
            for (var k in obj) {
                this[k]=(typeof obj[k] == 'object')?new clone(obj[k]):obj[k];
            }
        }

 

posted @ 2018-06-20 15:38  丶七月小先生丶  阅读(176)  评论(0编辑  收藏  举报