美文网首页JS笔记
JS-闭包和继承

JS-闭包和继承

作者: 壹枕星河 | 来源:发表于2019-03-27 15:17 被阅读31次

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

闭包(closure)

闭包可以在全局函数里面操作另一个作用域的局部变量, 既能重复使用,又不会污染全局
闭包有三步:

1、外层函数嵌套内层函数
2、内层函数使用外层函数的局部变量
3、把内层函数作为外层函数的返回值

1-预解析.png 2-调用时.png 3-调用后.png 4-fn调用时.png 5-fn调用后.png
继承

子类共享父类的属性和方法,js的继承都是基于原型实现的
1.原型链继承:子类的原型指向父类的实例

 function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
var cat = new Cat();
console.log(cat.name);
cat.say();
cat.eat('fish');
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true

特点:

  1. 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
  2. 父类新增原型方法/原型属性,子类都能访问到
  3. 简单,易于实现

缺点:

  1. 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中
  2. 无法实现多继承
  3. 来自原型对象的引用属性是所有实例共享的
  4. 创建子类实例时,无法向构造函数传参

2. 构造继承(call、apply继承)

 function Cat(name){
    Animal.call(this,name);
}
var cat = new Cat("Tom");
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特点:

  1. 解决了1中,子类实例共享父类引用属性的问题
  2. 创建子类实例时,可以向父类传递参数
  3. 可以实现多继承(call多个父类对象)

缺点:

  1. 实例并不是父类的实例,只是子类的实例
  2. 只能继承父类的实例属性和方法,不能继承原型属性/方法
  3. 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

3.拷贝继承

function Cat(name){
    var animal = new Animal(name);
    for(var key in animal){
        Cat.prototype[key] = animal[key];
    }
}
// Test Code
var cat = new Cat("Tom");
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特点:

支持多继承

缺点:

  1. 效率较低,内存占用高(因为要拷贝父类的属性)
  2. 无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)

4. 组合继承(原型链和构造继承的组合)

function Cat(name){
    Animal.call(this,name);
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
// Test Code
var cat = new Cat();
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true

特点:

1.弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法

  1. 既是子类的实例,也是父类的实例
  2. 不存在引用属性共享问题
  3. 可传参
  4. 函数可复用

缺点:

调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

5.寄生组合继承

function Cat(name){
    Animal.call(this);
    this.name = name;
}
(function(){
    // 创建一个没有实例方法的类
    var Super = function(){};
    Super.prototype = Animal.prototype;
    //将实例作为子类的原型
    Cat.prototype = new Super();
})();
// Test Code
var cat = new Cat();
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

特点:堪称完美
缺点:实现较为复杂

6. ES6继承(语法糖)

class Animal{
    constructor(name){
        this.name = name;
    }
    say(){
        alert("My name is "+this.name);
    }
    eat(food){
        alert(this.name+" is eating "+food);
    }
}
class Cat extends Animal{
    constructor(name){
        super(name);
    }
}
var  tom = new Cat("Tom");
tom.say();
tom.eat("apple");
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

相关文章

  • JS-闭包和继承

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

  • js-继承和闭包

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

  • 闭包和继承

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

  • js-闭包

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

  • js-闭包

  • Js-闭包

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

  • js-闭包

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

  • JS-闭包

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

  • js-闭包

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

  • JS-闭包

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

网友评论

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

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