zoukankan      html  css  js  c++  java
  • 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。浪费内存,影响性能。

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

        

      

        

  • 相关阅读:
    UOJ.26.[IOI2014]Game(交互 思路)
    Good Bye 2016 F.New Year and Finding Roots(交互)
    Codeforces.835E.The penguin's game(交互 按位统计 二分)
    Codeforces.744B.Hongcow's Game(交互 按位统计)
    Codeforces.862D.Mahmoud and Ehab and the binary string(交互 二分)
    正睿OI 提高 Day1T3 ZYB玩字符串(DP)
    划分vlan
    2三层交换机实现vlan间的路由
    交换机基础-交换机远程telnet
    自动化运维环境的搭建问题处理
  • 原文地址:https://www.cnblogs.com/xhrr/p/11172927.html
Copyright © 2011-2022 走看看