zoukankan      html  css  js  c++  java
  • 继承(学习笔记) —— 《高级教程》

    继承

    原型链

     先不管上图,先来看以下代码:

     
    function Person() {
        this.personName = 'person';
    }
        
    Person.prototype.sayPersonName = function() {
        console.log(this.personName);
    }
        
    function Student() {
        this.studentName = 'student';
    }
    
    Student.prototype = new Person(); // Student 的原型对象替换为 Person 的实例对象 参考上图中右边第一条红线
    
    Student.prototype.sayStudentName = function() {
        console.log(this.studentName);
    }
    
    var student1 = new Student();
    student1.sayPersonName(); // person
    student1.sayStudentName(); // student
     

    结合代码和上图,可以清楚得看到,将某个构造函数的原型对象替换为另一个构造函数的实例对象后,最终的指向(图中红线部分,就像链条一样,层层链接)。这就是原型链的基本概念。

     

    coding:

     1 function Myarray(){
     2   this.name = 'myarray';
     3 }
     4 
     5 Myarray.prototype = new Array();
     6 
     7 var arr1 = new Myarray();
     8 
     9 console.log(arr1.name);
    10 
    11 arr1.unshift(3);
    12 arr1.unshift(2);
    13 arr1.unshift(4);
    14 arr1.push(5);
    15 arr1.sort();
    16 
    17 console.log(arr1 instanceof Array);;
    18 arr1.forEach(
    19   function(ele,index){
    20     console.log(index+":"+ele);
    21   }
    22 )

    默认的原型

    所有引用类型默认都继承了 Object,这也是通过原型链实现的。

    确定原型和实例的关系

    • instanceof
    • isPrototypeOf()

    instanceof

    console.log(student1 instanceof Student); // true
    console.log(student1 instanceof Person); // true
    console.log(student1 instanceof Object); // true

    student1 是 Student, Person, Object 三者中任意一个类型的实例。

    isPrototypeOf()

    console.log(Student.prototype.isPrototypeOf(student1)); // true
    console.log(Person.prototype.isPrototypeOf(student1)); // true
    console.log(Object.prototype.isPrototypeOf(student1)); // true

    借用构造函数(constructor stealing)

    在子类型构造函数的内部借用超类型构造函数。

     
    function Person() {
        this.friends = ['Mike', 'Lily', 'Melinda'];
    }
    
    function Student() {
        Person.call(this); // 调用一遍 Person 构造函数,在新 Student 对象上执行 Person 函数中定义的所有对象初始化代码,每个实例都会有自己的属性的副本
    }
    
    var student1 = new Student();
    student1.friends.push('Lucy');
    console.log(student1.friends); // ["Mike", "Lily", "Melinda", "Lucy"]
    
    var student2 = new Student();
    console.log(student2.friends); // ["Mike", "Lily", "Melinda"]
     

    优点:可以传递参数。

     
    function Person(name) { // <-- 参数
        this.friends = ['Mike', 'Lily', 'Melinda'];
        this.name = name;
    }
    
    function Student(name) {
        Person.call(this, name); // <-- 传入参数
    }
    
    var student1 = new Student('John');
    console.log(student1.name); // John
    
    var student2 = new Student('Gray');
    console.log(student2.name); // Gray
     

    缺点

    • 方法都在构造函数中定义,无法实现方法复用
    • 在超类型的原型中定义的方法,子类型不可见

    组合继承(combination inheritance)

    原型链和借用构造函数的组合

     
    function Person(name) {
        this.name = name;
    }
    
    Person.prototype.sayName = function() {
        console.log(this.name);
    }
    
    function Student(name, age) {
        Person.call(this, name);
        this.age = age;
    }
    
    Student.prototype = new Person();
    Student.prototype.constructor = Student;
    Student.prototype.sayAge = function() {
        console.log(this.age);
    }
    
    var student1 = new Student('Mike', 28);
    student1.sayName(); // Mike
    student1.sayAge(); // 28
     

    原型式继承(prototypal inheritance)

    借助原型基于已有的对象创建新对象。

     
    function object(obj) {
        function fn() {
            
        }
        fn.prototype = obj;
        return new fn();
    }
    
    var obj = {
        name: 'Miker',
        sayName: function() {
            console.log(this.name);
        }
    }
    var newObj = object(obj);
    newObj.name = 'John';
    console.log(newObj.name); // John
    newObj.sayName(); // John
     

    Object.create(obj, {});

    寄生式继承(parasitic)

     
    function createAnother(original) {
        var clone = object(original); // <-- 调用原型式继承的方法
        clone.sayHi = function() { // <-- 增强这个对象
            console.log('Hi');
        }
        return clone; // 返回这个对象
    }
     

    寄生组合式继承

    组合继承的缺点:调用两次超类型构造函数。

     
    function Person(name) {
        this.name = name;
    }
    
    Person.prototype.sayName = function() {
        console.log(this.name);
    }
    
    function Student(name, age) {
        Person.call(this, name); // <-- 第二次调用超类型构造函数
        this.age = age;
    }
    
    Student.prototype = new Person(); // <-- 第一次调用超类型构造函数
    Student.prototype.constructor = Student;
    Student.prototype.sayAge = function() {
        console.log(this.age);
    }
     

    改造:

     
    function object(obj) {
        function fn() {
            
        }
        fn.prototype = obj;
        return new fn();
    }
    
    function inheritPrototype(subType, superType) { // <-- 原型继承
        var prototype = object(superType.prototype); // 原型对象
        prototype.constructor = subType;
        subType.prototype = prototype;
    }
    
    function Person(name) {
        this.name = name;
    }
    
    Person.prototype.sayName = function() {
        console.log(this.name);
    }
    
    function Student(name, age) {
        Person.call(this, name);
        this.age = age;
    }
    
    inheritPrototype(Student, Person);
    
    Student.prototype.sayAge = function() {
        console.log(this.age);
    }
    
    var student1 = new Student('Mike', 28);
     

    画了一张关系图,仅供参考

    以上内容转自:http://www.cnblogs.com/lwl0812/p/9818192.html

  • 相关阅读:
    2014多校第四场1005 || HDU 4901 The Romantic Hero (DP)
    HDU 1698 Just a Hook (线段树区间更新)
    HDU 1016 Prime Ring Problem (素数筛+DFS)
    2014多校第二场1011 || HDU 4882 ZCC Loves Codefires (贪心)
    HDU 1142 A Walk Through the Forest(SPFA+记忆化搜索DFS)
    JSP九大内置对象和四个作用域
    Jsp遍历后台传过来的List
    JavaWeb文件上传和下载
    servlet中doGet()和doPost()的区别
    Ajax请求会话过期处理(JS)
  • 原文地址:https://www.cnblogs.com/johnhery/p/9818274.html
Copyright © 2011-2022 走看看