• JavaScript高级


    面向对象

      好处:易于分工与合作,适合大型项目开发;健壮性强,易于维护

      特征:封装、继承、多态      

    1. 原型

      1. 学习原型理由

        问题:每创建一个对象,都会在对象中添加一个方法,方法是不变的,若创建每个对象会造成内存浪费。

        解决:把方法抽取出来,让所有 实例对象共享。

        实现共享:使用原型(把方法封装到原型中)

      2. 什么是原型

        原型也是一个对象

        1. 获取原型的方式:构造函数名.prototype

        2. 构造函数与原型的关系

          * 构造函数可以通过prtotype找到原型

          * 原型可以通过construcror找到构造函数

      3. 原型链

        实现对象在调用一个属性和方法时过程如下:

          ①会先从实例对象中找

          ②若自身没有找到则通过__prot__找到原型,去原型中找

          ③若原型中没有,则通过原型的__proto__找到原型的原型去找

          之所以会找到因为原型链的存在

    2. 继承

      1. 利用原型实现继承

        更改子类的原型指向(或给子类的原型重新赋值)

    //定义person构造函数
    function Person(){
      this.name = '名字';
      this.age = 10;
      this.gender = '男';      
    }
    //给构造函数原型添加方法
    Person.prototype.sayhi = function(){
         console.log('hi')
    }
    //实例化对象p1
    var p1 = new Person()
    
    //定义student构造函数
    function Student(){
        this.stuId = '10100';
    }
    
    Student.prorotype = p1;
    
    //实例化学生对象
    var stu1 = new Student();
    console.log(s1.name);     //输出name值是p1.name的值
    

        原型继承的问题和优点:

          缺点:继承的属性是没有意义的;

          优点:继承的方法是有意义的;

      2. 借用继承

        call方法改变this指向

        函数体内的this指向是在函数调用时决定的(指向调用者)

        语法:函数名.call( 调用者,参数 )

        作用:该函数会立即执行,但函数体内的this会指向借用者

    function fn(n, a){
        this.name = n;
        this.age = a;
    }
    //定义对象
    var obj1 = {type: 'obj'};
    //fn借用给obj1
    fn.call( obj1, '展示', 11)
    

        call方法实现借用

          在子类构造函数中借用父类构造函数,并且在 call 中传入子类对象

    //per构造函数
    function Per(n,a){
        this.name = n;
        this.age = a;
    }
    
    Per.prototype.sayhi = function(){
      console.log(this.name + 'hi')      
    }
    //stu构造函数
    function Stu(n,a){
        this.sid = '10001'
        Per.call(this, n, a)    //Per谁调用借给谁
    }
    var s1 = new Stu('栈', 23)
    console.log(s1.name);     //输出栈
    

        借用继承的问题和优点

          缺点:仅仅借用了属性(原因:call方法在被per类调用执行时仅仅让调用者执行函数内部的程序,函数外的没有借用执行)

          优点:很好的继承属性

          解决:原型+借用

      3. 组合继承

        原型:借用方法    +   借用:继承属性

    //创建per构造函数
    function per(n, a){
      this.name = n;
      this.age = a;
    }
    //为per添加原型
    per.prototype.sayhi = function(){
        console.log(this.name + 'hi')
    }
    
    //创建stu构造函数
    function stu(n,a){
        this.sid = '1001011'
        //借用属性
        per.call(this, n, a)
    }
    //借用方法
    stu.prototype = per.prototype
    var s1 = new stu('组件', 22)
    console.log(s1.name)     //输出组件
    s1.sayhi()    //输出组件hi
        
    

        组合继承问题:

          缺点:stu类和per指向同一个原型,stu的原型改变时人类的原型也会被改变

          优点:让他们不要指向同一个原型,使用各自的原型(对象之间的拷贝)

      4. 对象之家的拷贝

        对象B拷贝对象A的属性和方法

    //一个对象拷贝另一个对象中的属性和方法,parentObj父对象  childObj子对象
    function copy(parentObj, childObj){
        for(var key in parentObj){
            if( childObj[kye] == undefined ){
                childObj[key] = parentObj[key];
            }
        }
    }
    //对象A
    var wjl = {
        name: '大熊',
        money: 100,
        house: '大屋子',
        cars: ['qq', '11'],
        sayhi: function(){
            console.log('大家好,我叫'+this.name);
        }
    }
    //对象B
    var wsc = {
        name: '小熊'
    }
    copy(wjl,wsc)
    

      5. 拷贝+ 借用组合继承

        拷贝方法 + 借用属性

        // 【人类】
        function Person(name, age, gender) {
          this.name = name;
          this.age = age;
          this.gender = gender;
        }
        Person.prototype.sayHi = function () {
          console.log('大家好....O(∩_∩)O哈哈~,我叫' + this.name);
        }
        Person.prototype.eat = function () {
          console.log('我会吃饭.....');
        };
    
        // 【学生类】
        function Student(name, age, gender) {
          // this代表谁?代表一个学生的实例对象 s1、s2
          this.stuId = '10010';
          // --借用函数--Person[仅仅借用函数体中内容,并没有借用函数体之外其他程序]
          Person.call(this, name, age, gender)
        };
    
        // [拷贝人类原型(wjl)中的方法给学生原型(wsc)]
        copy(Person.prototype, Student.prototype);
        Student.prototype.test = function() {
          console.log('我超爱考试');
        }
        // 【老师类】
        function Teacher(name, age, gender) {
          // 借用继承-借用人类的属性
          Person.call(this, name, age, gender);
        }
        // [拷贝人类原型(wjl)中的方法给老师原型(wsc)]
        copy(Person.prototype, Teacher.prototype);
    
        // 创建学生对象
        var s1 = new Student('张三',19,'男');
        // 创建老师对象
        var t1 = new Teacher('李四',39,'男');
    

    3. this指向

      普通函数中this指向window

      构造函数中this指向当前所创建的对象 

      定时器中this指向window

      对象方法中的this指向调用者

      事件处理程序中this指向事件源

    4. 改变函数内部this指向

      1. apply

        语法:函数名.apply( 调用者,[参数......] )

        作用:函数被借用时,会立即执行,并且函数体内的this会指向借用者

      2. bind方法

        语法:函数名.apply(调用者, 参数.......)

        作用:函数被借用时,不会立即执行,返回新的函数。函数体内this指向调用者

    5. 闭包

      1. 什么是闭包

        闭包就是能够读取/设置  他函数 内部变量的函数;闭包就是将函数内部和函数外部链接起来的桥梁。

      2. 闭包的用途

        可以在函数外部读取函数函数内部成员;让函数内成员始终活在内存中(延长变量生命周期)

      3. 如何实现闭包

        ①函数嵌套

        ②外层函数,必须要有局部变量

        ③内部函数必须要操作外层函数的局部变量,并且在外层中返回内层函数或内层函数在外部被间接的调用。

        调试:在内层函数中设置断点,若进入来在右侧中的scope下可以看到closure,就表示产生了闭包。  在实际开发中,不要可以使用闭包,因为延长生命周期的变量可能会一直存活在内存中。  解决方案:把外层变量设置为null

    6. 递归

      作用:减少代码量

      缺点:若递归的层数比较多时,会消耗CPU。浪费内存,影响性能。

    若将来递归层较少时,可以选择用递归方式。

        

      

        

  • 相关阅读:
    canvas,画个纸飞机
    时钟
    去除滚动条,内容仍然可以滚动
    鼠标指针移入移出改变图片透明度
    Mysql数据库优化总结
    一次利用nginx漏洞的木马事件
    一个批量删除大表数据的shell小脚本
    MegaCli监控raid卡磁盘信息以及相关的shell脚本
    MYSQL delete语句不支持别名?
    一次Mysql数据库服务器磁盘空间满引发的写入和同步问题
  • 原文地址:https://www.cnblogs.com/xhrr/p/11172927.html
Copyright © 2020-2023  润新知