欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

js面向对象编程/原型链/继承 —— javascript

程序员文章站 2022-10-04 11:38:52
目录 js面向对象编程 js原型链 共享方法 原型继承 class继承 js面向对象编程 js原型链 共享方法 原型继承 class继承 js面向对象编程 js面向对象编程不同于 java 的类和对象 JavaScript 不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。 ......

目录

 

js面向对象编程

js面向对象编程不同于 java 的类和对象

javascript 不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。

js声明的构造函数,类似于普通函数的声明,但又不同,

实例对象时,如果不写new,就是一个普通函数,它返回 undefined。

但是,如果写了new,它就变成了一个构造函数,它绑定的 this 指向新创建的对象,

并默认返回 this,也就是说,不需要在最后写return this;。

 

js原型链

 代码段一:

function student(name){
    this.name = name;
    this.say = function(){
        console.log('my name:', this.name);
    }
}

let student1 = new student('student1');
let student2 = new student('student2');

js面向对象编程/原型链/继承 —— javascript

console.log(student1.constructor === student.prototype.constructor)        // true 

橙色箭头表示原型链,其原型链为:

student1 --> student.prototype --> object.prototype --> null

当我们用 obj.xx 访问一个对象的属性时,javascript引擎先在当前对象上查找该属性,

如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到object.prototype对象,

最后,如果还没有找到,就只能返回undefined

 

共享方法

代码段二:

function student2(){
    this.say = function(){
        console.log('hi')
    }
}
console.log(new student2().say === new student2().say)

 结果:

false

实例化的对象方法,虽然方法名称和代码完全一样,但是不同对象指向的不是同一个方法

需要创建一个共享的方法,

根据原型链图,需要将这个共享方法声明在 student2 的原型对象上,

xxx.prototype.xxx = function(){}

function student2(){
    this.say = function(){
        console.log('hi')
    }
}

student2.prototype.publicsay = function(){
    console.log('public say');
}

console.log(new student2().say === new student2().say)
console.log(new student2().publicsay === new student2().publicsay)

 结果:

false
true

 

原型继承

学过 java 的都知道,类的继承通过 extends 会很容易实现,

但是 javascript原型继承有点麻烦,不过 class继承就很方便

function father(name){
    this.say = function(){
        console.log(name)
    }
}
function son(name){
    father.call(this, name)
}

console.log(son.prototype.__proto__)   // object

这样看似继承了,但是其原型链的指向并没有改变

其原型链图为:

js面向对象编程/原型链/继承 —— javascript

要实现原型继承,看图的话很容易,只需要将 son 的原型对象的原型指向 father 的原型对象

 js面向对象编程/原型链/继承 —— javascript

要实现原型继承,这里有三种方法,

 法一:

这个方法简介明了,但是不推荐直接通过 __proto__ 直接改变原型

function father(name){
    this.say = function(){
        console.log(name)
    }
}
function son(name){
    father.call(this, name)
}

son.prototype.__proto__ = father.prototype;
console.log(son.prototype.__proto__)    // father

 

法二:

通过实例化 father 生成一个对象,

new father() 的原型会默认指向 father 的原型

通过修改 sonprototype 属性和 new father()constructor 属性,

来绑定 sonnew father() 之间的关系

js面向对象编程/原型链/继承 —— javascript

function father(name){
    this.say = function(){
        console.log(name)
    }
}
function son(name){
    father.call(this, name)
}

son.prototype = new father();
son.prototype.constructor = son;

console.log(son.prototype.__proto__)    // father

 

法三:

 类似法二,声明一个中间对象来改变指向

js面向对象编程/原型链/继承 —— javascript

mid.prototype = father.prototype;
son.prototype = new mid();
son.prototype.constructor = son;

第一步,将 mid 的原型对象指向 father 的原型对象,

第二步,将 son 的属性 prototype 指向 mid

  此时代码上的 new mid(),实际上是 new father()

第三步,将 son.prototype.constructor 也就是 mid.prototype.constructor 指向 son

js面向对象编程/原型链/继承 —— javascript

看起来有点乱,看数字步骤,方便理解

function father(name){
    this.say = function(){
        console.log(name)
    }
}
function son(name){
    father.call(this, name)
}

mid.prototype = father.prototype;
son.prototype = new mid();
son.prototype.constructor = son;

console.log(son.prototype.__proto__)  // father

class继承

es6 提供了关键字 class,定义类变得更便捷

共享方法

class father{
    // 构造方法
    constructor(name){
        this.name = name;
    }
    hello(){
        console.log("hello", this.name)
    }
}

console.log(new father("f").hello === new father("f").hello)
// true,共享方法

class继承

class father{
    // 构造方法
    constructor(name){
        this.name = name;
    }
    hello(){
        console.log("hello", this.name)
    }
}

class son extends father{
    constructor(name){
        super(name);
    }
}

console.log(son.prototype.__proto__)    // father