美文网首页
js-继承和闭包

js-继承和闭包

作者: 橙赎 | 来源:发表于2020-03-31 18:13 被阅读0次

继承和闭包

一、面向对象的三大特征

  • 封装
  • 继承
  • 多态

二、什么是继承

继承是面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

三、继承的三种方法

  • 1.call方法
 // 构造函数-Person
        function Person(name, age) {
            this.name = name;
            this.age = age;
            this.Say = function () {
                console.log("吃东西")
            }
        }
        // 构造函数-Student来继承Person
        function Student(name,age){
            Person.call(this,name,age)
        }
        const s1 = new Student('张三',24);
        console.log(s1.name,s1.age);
        s1.Say();

但是上述方法不能继承原型对象的属性和方法

  • 拷贝继承
 //人-构造函数
        function Person(name, age) {
            this.type = 'human'
            this.name = name
            this.age = age
            this.say = function () {
                console.log("说话>>");
            }
        }
        Person.prototype = {
            constructor: Person,
            eat: function () {
                console.log('吃东西');
            }
        }

        //学生-构造函数
        function Student(name, age) {
            Person.call(this, name, age); // 借用构造函数继承成员
        }

        // 原型对象拷贝继承原型对象成员
        for (const key in Person.prototype) {
            Student.prototype[key] = Person.prototype[key];
        }

        var s1 = new Student('张三', 18)
        console.log(s1.type, s1.name, s1.age) // => human 张三 18
        s1.say();
        s1.eat();
  • 原型继承
      function Person(name, age) {
            this.type = 'human'
            this.name = name
            this.age = age
        }

        Person.prototype.sayName = function () {
            console.log('hello ' + this.name)
        }

        function Student(name, age) {

        }

        // 利用原型的特性实现继承
        Student.prototype = new Person()

        var s1 = Student('张三', 18)

        console.log(s1.type) // => human

        s1.sayName() // => hello 张三

四、函数的this指向问题

调用方式 非严格模式 备注
普通函数调用 window 严格模式下是undefined
构造函数调用 实例对象 原型方法中的this也是实例对象
对象方法调用 该方法所属对象 紧挨着的对象
事件绑定方法 绑定事件的对象
定时器函数 window

如下例所示:

 //普通函数调用
    const info = function(){
        console.log('普通函数this  :',this);
    }
    //info(); //window
    // 构造函数调用
    function Person(){
        console.log('构造函数this ',this);//Person
        this.name = '构造函数'
        this.sayName = function(){
            console.log('对象方法this ',this);//Person
        }
    } 
    // 原型对象
    Person.prototype.eat = function(){
        console.log('原型方式this :',this);//Person
    }

    Person.prototype.eat = () => {
        console.log('原型方式this :',this);//箭头函数里没有this,该this指向为外层,即window
    }

    const p = new Person();
    p.sayName();
    p.eat();

    // 事件绑定
    const btn  = document.getElementById('btn');
    btn.onclick = function(){
        console.log('事件绑定this ',this);//<button id="btn">按钮</button>
    }
    // 定时器
    setTimeout(function(){
        console.log('定时器this',this);
    },1000)//window

五、call()和apply()的区别和作用

call()apply()都可以改变this的指向

区别:它们的区别在于接受的参数方式不同

  • call():第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。在使用call()方法时,传递给函数的参数必须逐个列举出来
  • apply():传递给函数的是参数数组

六、闭包

1.变量作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

 var n=999;
  function f1(){
    alert(n);
  }
  f1(); // 999

另一方面,在函数外部自然无法读取函数内的局部变量。

function f1(){
    var n=999;
  }
alert(n); // error
2.闭包

出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。

那就是在函数的内部,再定义一个函数,只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了

function f1(){
    var n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999

上面代码的f2函数就是闭包,简单理解为:闭包就是能够读取其他函数内部变量的函数

闭包形成的条件:

  • 函数嵌套
  • 内部函数引用外部函数的局部变量
3.闭包的用途和特点
  • 闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
//例题1
var inner;
function outer(){
  var a=250;
  inner=function(){
    alert(a);//这个函数虽然在外面执行,但能够记忆住定义时的那个作用域,a是250
  }
}
outer();
var a=300;
inner();//一个函数在执行的时候,找闭包里面的变量,不会理会当前作用域。

//例题2
function outer(x){
  function inner(y){
    console.log(x+y);
  }
  return inner;
}
var inn=outer(3);//数字3传入outer函数后,inner函数中x便会记住这个值
inner(5);//当inner函数再传入5的时候,只会对y赋值,所以最后弹出8

相关文章

  • JS-闭包和继承

    函数在创建的时候会创建两个对象,一个是函数对象本身,另一个是作用域链对象函数在调用的时候会创建一个执行环境对象(活...

  • js-继承和闭包

    继承和闭包 一、面向对象的三大特征 封装 继承 多态 二、什么是继承 继承是面向对象软件技术当中的一个概念,与多态...

  • 闭包和继承

    闭包 嵌套的内部函数引用外部函数内的参数,外部调用时全局有一个变量就形成了闭包,执行函数后由于内部函数引用了参数,...

  • js-闭包

    对于闭包的理解,一直很浅懂,特别有时候跟匿名函数混淆。所以收集下面各路对于闭包的讲解。 维基百科中的解释:“在计算...

  • js-闭包

  • Js-闭包

    「闭包」 要理解什么闭包,首先要知道闭包为啥出现,实际代码中,我们想在某一的作用域中使用一个变量,很简单,直接在外...

  • js-闭包

    为什么写闭包: 1.被人说复杂,想整清晰.其实很好理解. 2.闭包在开发中用途很多.面试经常问,必须弄懂. 为什么...

  • JS-闭包

    一、闭包简介1、函数内部的函数可以生成闭包2、闭包的应用:需要多个内部变量值3、闭包弊端闭包:会倒致函数运行结束后...

  • js-闭包

    了解闭包前,先了解变量:局部变量和全局变量。 接下来的问题是,如何从外部获取局部变量: 如上,f5可以读取f4中的...

  • JS-闭包

    0.闭包 理解闭包的关键在于:外部函数调用之后其变量对象本应该被销毁,但闭包的存在使得我们仍旧可以访问外部函数的变...

网友评论

      本文标题:js-继承和闭包

      本文链接:https://www.haomeiwen.com/subject/fmiwuhtx.html