美文网首页
JS类_类的实例_继承

JS类_类的实例_继承

作者: 大猫城堡 | 来源:发表于2019-01-17 15:30 被阅读0次

类, 类的实例,类的构造函数,类的成员函数/类原型

1: 类: 具有相同类型的一类实例的逻辑描述;
2: 类的实例: 被构造函数出来的具有这个类的实例特征的一个表;
3: 类的成员函数: 完成对应的逻辑,通过this来操作不通的实例;

//  “function Person”叫做类的构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
}

// “.get_age”叫做类的方法,又叫做类的成员函数
// 用 this 操作类的实例来完成特定的逻辑;
Person.prototype.get_age = function() {
    return this.age;
}

Person.prototype.get_name = function() {
    return this.name;
}
// end

var xiaoming = new Person("xiaoming", 12);

//new 函数的作用相当于手写了下面这样的一个表:
var my_person = {
    //数据
        name: "xxxxx",
    age: 12,
        
        //成员函数
    __proto__: {
        get_name: Person.prototype.get_name,
        get_age: Person.prototype.get_age,
    }
};

//“xiaohong”叫做类的实例
var xiaohong = new Person("xiaohong", 13);
var xiaotian = new Person("xiaotian", 13);

console.log(xiaotian);
console.log(xiaohong);
console.log(xiaoming);


xiaotian.get_name();
xiaoming.get_name();
xiaotian.get_name();

// xiaotian, xiaoming, xiaohong 者三个实例都有相同的结构:
// 1:每个人实例 都有 name, age,
// 2: 每个实例都有一个 (函数)方法get_name, get_age;
// 他们这三个实例,属于同一个类型;
// 或者说他们三个实例,都是Person类
// 把Person看作是一个类, xiaotian, xiaoming,xiaohong可以看作是类的 3个实例;

举一个例子:新建一个Enemy.js文件,写入

// 类
function Enemy(name, level) {
    this.name = name;
    this.level = level;
}

// “Enemy.prototype”这个表我们又把他叫做“类原型”;
Enemy.prototype.attack_player = function() {
    console.log("attack_player", this);
}
// 类结束

module.exports = Enemy;
在 main.js 文件中
var Enemy = require("./Enemy")

var e1 = new Enemy("e1", 1);
e1.attack_player();

var e2 = new Enemy("e2", 2);
e2.attack_player();

继承

为何要用继承?

为了扩展“类的原型”,类的原型不需要构造函数里的实例

例1:继承机制: 猫的代码---> 波斯猫的代码(在猫的代码的基础上扩展波斯猫的代码
例2:敌人--> 扩展成特殊的敌人。在原来敌人的基础上--> 继承原来的代码, --> 再添加;


实现继承,例如:

  1. new 机制使得 Cat 的空表"__ proto __"被创建,并携带参数 name "Black Cat"
  2. 然后化身为函数 Cat 中的 this
  3. 接着被 .call 显式传递给函数 Animal 中的 this,并携带参数name "Black Cat"
  4. 执行函数 Animal,意味着向 Cat 表中添加和函数 Animal相同地 key 和 value
  5. 打印出 "Black Cat"
function Animal(name){
    this.name = name;
    this.showName = function(){
        console.log(this.name);
    }
}

function Cat(name){
    Animal.call(this, name);
}

var cat = new Cat("Black Cat");
cat.showName();

// step1: 创建一个BossEnemy的构造函数;

function BossEnemy(name, level) {
--------------------------------------------------------------------------------
    // 调用基类的构造函数
    // 如何继承“构造函数里的成员”?
    // new 一个 "BossEnemy",就是在表 BossEnemy 下新建一个类原型__proto__空表
    // 因为在 new 机制下,函数 BossEnemy 下的 this,就是类原型__proto__空表
    // 接着被 .call 显式传递给构造函数 Enemy,构造函数 Enemy 下的 this,就被传递为表 BossEnemy 下的类原型__proto__空表
    // 执行构造函数 Enemy,将构造函数 Enemy 下的实例,添加到表 BossEnemy 下的类原型__proto__空表
    // 又因为在 new 机制,会返回表 BossEnemy 下的类原型__proto__表
    // 当 var boss = new BossEnemy("通天教主", 10) 时
    // 意思是表 BossEnemy 下的类原型__proto__空表,携带着由参数name, level 分别传过来的 "通天教主", 10
    // 被传入到构造函数 Enemy 中,执行的内容是向类原型__proto__空表里添加数据
    // key = name,value = 参数name
    // 所以最终返回的表,就是 attack_player Enemy { name: '通天教主', level: 10, blood: 100 }
    Enemy.call(this, name, level) //这里的this 是 new BossEnemy() 的空表

    // 如何扩展自己的成员?
    this.blood = 100;
}

// step2: 把 Enemy 里面所有的原型方法,都复制过来;

// 注意:不能直接这样写。当我们修改BossEnemy.prototype原型的时候,同时也会修改到Enemy.prototype。
// 因为他们两个变量都指向同一个“表的实例”,所以要新建一个表
// BossEnemy.prototype = Enemy.prototype; 

--------------------------------------------------------------------------------
// 如何继承“构造函数 Enemy 的表 prototype”?
// 写法1
BossEnemy.prototype = {};
for(var i in Enemy.prototype) {
    BossEnemy.prototype[i] = Enemy.prototype[i];
}

// “规范的”写法2
// 通过下面这两行,var a 就相当于构造函数
// 要继承基类 Enemy.prototype,只继承 prototype。
// 如果直接 new 一个Enemy,除了继承它的 prototype
// 还会把函数 Enemy 里的数据(this.xxx) 全都拿过来。

var a = function() {}
//a.prototype 指向 Enemy.prototype
a.prototype = Enemy.prototype;
// 用 new 函数4个步骤,把类的原型 Enemy.prototype 复制到表__proto__中。
BossEnemy.prototype = new a(); // {__proto__: Enemy原型}

--------------------------------------------------------------------------------
// 如何扩展原型?
// 获取到原型以后,就继承了 Enemy 的原型方法;
BossEnemy.prototype.boss_attack = function() {
    console.log("boss_attack");
}

var boss = new BossEnemy("通天教主", 10);
// 表的访问
boss.boss_attack();
boss.attack_player();

--------------------------------------------------------------------------------
// 重载
// 根据优先找到表 BossEnemy.prototype.attack_player 的,会把Enemy.prototype.attack_player 冲掉
BossEnemy.prototype.attack_player = function() {
    //调用基类的 prototype
    Enemy.prototype.attack_player.call(this);
// 这里的 this,还是 new BossEnemy 的表
    console.log("BossEnemy get name");
    return this.name;
}

boss.attack_player();
/*
打印出:
attack_player Enemy { name: '通天教主', level: 10, blood: 100 }
BossEnemy get name
*/

Class函数

javascript 没有类,继承语法的, new, this, 模拟,有些地方些了一个继承函数。这个Class函数,能帮我们得到新的类

function Class(class_desic) {
    var new_class = function(name, level) {
        if (class_desic.extend) { // 有基类
            // 调用基类的构造函数
            class_desic.extend.call(this, name, level);
        }
        // 加一个初始化的接口 
        if (class_desic.init) {
            class_desic.init.call(this);
        }
    }

    if (class_desic.extend) {
        var a = function() {};
        a.prototype = class_desic.extend.prototype;
        new_class.prototype = new a();  
    }
    else {
        new_class.prototype = {};   
    }

    for(var i in class_desic) {
        if (i == "extend") {
            continue;
        }
        new_class.prototype[i] = class_desic[i];
    }


    return new_class;
}

var BossEnemy2 = Class({
    // 定义写死的关键字 extend 是继承自那个基类
    extend: Enemy, // 对象的名字

    init: function(){

    },

    boss_attack: function() {

    },

    add_blood: function() {
        console.log("add_blood", this);
/* 
这里的 this 指的也是 b2 的 this
b2 的实例显式的绑定过来
这里的 this 也是指后面调用的实例
*/
    },
});

var b2 = new BossEnemy2("boss2", 1111);
console.log(b2);
b2.add_blood();

相关文章

  • JS类_类的实例_继承

    类, 类的实例,类的构造函数,类的成员函数/类原型 1: 类: 具有相同类型的一类实例的逻辑描述;2: 类的实...

  • js面向对象实现面向对象(二)

    上一篇讲到js实现对类对封装,本篇介绍类的继承,多态。 类的继承 类式继承 类式继承方式是将父类的实例赋在子类的原...

  • js面向对象总结

    1、类与实例 类的声明 实例化 2、类与继承 继承的几种方式

  • Python-类和对象

    关键词:类、实例、继承、重载创建类: 创建类实例对象: 属性操作: 类的继承: 继承类定义时,括号内填写父类名称继...

  • javascript的六种继承方式

    js中常用的继承方式:子类继承父类的方法 1、原型继承 子类的原型指向父类的一个实例 父类的私有和公有方法都是子类...

  • JS实现继承 JavaScript

    JS实现继承 JavaScript 定义一个父类: 1.原型链继承 核心:将父类的实例作为子类的原型 特点: 非常...

  • js对象的继承

    js继承的实现方式 原型链继承 将父类的实例作为子类的原型,向子类的原型链中去构建一个父类的实例。 特点:1.非常...

  • 六、继承与多态 @GeekBand

    面向对象特征 封装 继承 单继承 继承了实例变量、属性、实例方法、类方法 所有类的根类:NSObject 成员复用...

  • js实现继承的几种方式

    JS继承的实现方式:既然要实现继承,那么首先我们得有一个父类,代码如下: 1、原型链继承核心: 将父类的实例作为子...

  • python基础-09-面向对象、装饰器

    面向对象 类概念 类的定义 类的实例化 类和实例的属性 类的私有变量 数据封装 继承 多态 多继承 类的特殊方法 ...

网友评论

      本文标题:JS类_类的实例_继承

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