类与继承

一、es5的类与继承

1. prototype原型对象

每个函数(普通函数、构造函数)都有一个prototype原型对象,每个prototype都有constructor属性,constructor指向函数本身
每个实例都有一个proto,指向构造函数的原型对象

function getSum(a,b){
    console.log(a+b)
}
function People(name,age){
    this.name = name;
    this.age = age;
}
getSum(1,2);
console.log(People.prototype.constructor)// People
console.log(getSum.prototype.constructor)// getSum
2. 静态方法和实例方法

① 在构造函数体中,this指向实例对象,通过this创建的属性属于实例属性
② 在构造函数原型对象上创建方法,方法内部this指向实例对象,属于实例方法
③ 直接挂在构造函数上的属性为静态属性、方法为静态方法,静态方法内的this指向构造函数本身
④ 直接调用构造函数,函数体内this指向调用时所处的作用域,即window

// 声明构造函数People
function People(name,age){
    console.log(this);// this指向实例对象
    this.name = name; //① 实例属性
    this.age = age; //① 实例属性
    People.count++;
}
// ② 实例方法,构造函数原型对象上的方法属于实例方法
People.prototype.showName = function(){
    console.log('我的名字是',this.name)
}
// ③ 静态属性,构造函数上的属性属于静态属性
People.count = 0;
// ③ 静态方法,构造函数上的方法属于静态方法
People.getCount = function(){ 
    console.log(this);// this指向构造函数本身
    console.log(this.count === People.count)//true ,此处等同于People
    console.log('目前共有',People.count,'个人')
}

let p1 = new People('xiaoyue1')
console.log(p1);
p1.showName();// 每个实例都能访问到原型对象上的方法和属性
let p2 = new People('xiaoyue2')
console.log(p2);
p2.showName();// 每个实例都能访问到原型对象上的方法和属性

console.log(People.count) //访问静态属性
People.getCount(); //调用静态方法
People('lily',18); // ④ 直接调用构造函数,函数题内部this指向当前作用域window

// 常见静态方法和属性
Math.max(1,2)
Math.PI
console.log(Math)// 查看Math上有哪些静态睡醒和静态方法
// 常见实例方法和属性
let arr = [1,2,3];
console.log(arr.slice(1))// slice为实例方法,slice、push、pop等这些方法都是挂在Array的构造函数上的
3. 类的继承,组合式继承

① 继承父类的属性:通过调用父类函数,call改变函数内this指向。People.call(this,name)
② 继承父类的方法:实例化一个父类的对象赋值给子类的原型对象,让子类实例通过自身的原型对象访问到父类的原型对象的方法。Student.prototype = new People();
③ 原型对象的constructor指回子类。Student.prototype.constructor = Student;

function Student(name,hobby){
    People.call(this,name);//① 继承属性:执行People函数,改变this指向为当前Student实例
    this.hobby = hobby; //实例自身属性
}
// ②实例化一个People对象peo,peo赋值给Student原型对象,实例对象peo能访问到People原型对象上所有的方法, 因此Student原型对象也能访问到People原型对象上的所有方法。
const peo = new People(); //实例化一个People对象peo
Student.prototype = peo; //赋值给Student原型对象
// Student.prototype = new People(); 或直接这样写
// ③赋值前,Student的prototype的constructor指向Student。
// ③赋值后,实例对象peo本身没有constructor,就会去new出它的构造函数People的原型对象上去找,但People的原型对象的constructor属性是指向People本身的。因此Student.prototype.constructor就会是People,得改回来,让它指回Student,如下。
Student.prototype.constructor = Student; //③
// 除了能访问到People的所有方法,还可以给Student原型对象添加属于自己的方法dance
Student.prototype.dance = function(){ 
    console.log('dance')
}
let s1 = new Student('yoyo','跳舞');
// console.log(Student.count) //undefined,继承不到静态属性和方法
// console.log(Student.getCount()) //报错, 继承不到静态属性和方法
console.log(s1)
s1.showName()
s1.dance()

练习题

console.log(s1.constructor === Student); //true
console.log(s1.constructor === People); //false
console.log(p1.constructor === People); //true
console.log(p1.__proto__ === People.prototype); //true
console.log(s1.__proto__ === Student.prototype); //true
console.log(s1.__proto__.constructor === Student); //true

二、es6的类与继承

1. 类

① class 声明类
② constructor 函数体
③ static 声明静态方法,不能声明静态属性
④ set和get 实例属性声明的另一种方式,可用于属性的读与写时的拦截处理

class People{ //①
    constructor(name){ //②函数体
        this.name = name; //实例属性
        this._sex = 0;
    }
    showName(){ //实例方法
        console.log(this.name)
    }
    // static count = 0; //会报错,es6还不支持这种static声明静态属性的写法!
    static getCount(){ //③静态方法
        // console.log(this) //静态方法this指向People,就是调用getCount时的.前面的那个对象
        console.log(this.count) //0
        console.log(this.count === People.count) //true
    }
    get sex(){ //④getter获取 
        if(this._sex === 0){
            return 'female'
        }else if(this._sex === 1){
            return 'male'
        }else{
            return 'error'
        }
    }
    set sex(val){ //④setter设置,只声明了set没声明get方法,设置时会报错
        if(val ===0 || val === 1){
            this._sex = val;
        }
    }
}
People.count = 0; //静态属性,目前只能这声明
let p1 = new People('yoyo');
console.log(p1);
console.log(p1.sex)
p1.sex = 1;
console.log(p1.sex)
2. 继承

extends继承内容:实例属性、实例方法、静态属性、静态方法、get/set属性

class Student extends People{
    constructor(name,hobby){
        super(name)
        this.hobby = hobby
    }
    study(){
        console.log('study')
    }
}
let s1 = new Student('yoyo','dance');
console.log(s1) 
console.log(s1.sex) //0 继承了get 和set声明的属性
s1.showName(); //继承了实例方法
console.log(Student.count) //0 继承了静态属性
console.log(Student.getCount()) //true 继承了静态方法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容