目录
js构造函数
原型
ES6继承方式
1、原型链继承
2、借用构造函数
3、组合继承
4、寄生组合继承
5、寄生组合继承(简直完美)
附YUI库实现继承
首页 web前端 js教程 js构造函数是什么?详解构造函数继承方法及优缺点

js构造函数是什么?详解构造函数继承方法及优缺点

Jul 27, 2018 pm 04:02 PM
javascript

js构造函数是什么?和普通函数有区别吗?这篇文章主要介绍js构造函数的继承(类的继承),也包括 ES5 和 ES6 两种继承方式的介绍,文章中如果有不合理的地方,也欢迎指正。

js构造函数

原型

首先简单介绍一下实例属性/方法 和 原型属性/方法,以便更好理解下文

function Persion(name){
    this.name = name;                                       // 属性
    this.setName = function(nameName){                      // 实例方法
        this.name = newName;
    }
}
Persion.prototype.sex = 'man';                              // 向 Persion 原型中追加属性(原型方法)

var persion = new Persion('张三');                          // 此时我们实例化一个persion对象,看一下name和sex有什么区别
登录后复制

在控制台查看 persion 打印如下:
1.png原来通过 prototype 添加的属性将出现在实例对象的原型链中,
每个对象都会有一个内置 proto 对象,当在当前对象中找不到属性的时候就会在其原型链中查找(即原型链)

我们再来看下面的例子
注意:在构造函数中,一般很少有数组形式的引用属性,大部分情况都是:基本属性 + 方法。

function Animal(n) {                                       // 声明一个构造函数
    this.name = n;                                         // 实例属性
    this.arr = [];                                         // 实例属性(引用类型)
    this.say = function(){                                 // 实例方法
        return 'hello world';
    }
}
Animal.prototype.sing = function() {                       // 追加原型方法  
    return '吹呀吹呀,我的骄傲放纵~~';
}
Animal.prototype.pArr = [];                                // 追加原型属性(引用类型)
登录后复制

接下来我们看一下实例属性/方法 和 原型属性/方法的区别
原型对象的用途是为每个实例对象存储共享的方法和属性,它仅仅是一个普通对象而已。并且所有的实例是共享同一个原型对象,因此有别于实例方法或属性,原型对象仅有一份。而实例有很多份,且实例属性和方法是独立的。

var cat = new Animal('cat');                               // 实例化cat对象
var dog = new Animal('dog');                               // 实例化狗子对象

cat.say === dog.say                                        // false 不同的实例拥有不同的实例属性/方法
cat.sing === dog.sing                                      // true 不同的实例共享相同的原型属性/方法

cat.arr.push('zz');                                        // 向cat实例对象的arr中追加元素;(私有)
cat.pArr.push('xx');                                       // 向cat原型对象的pArr中追加元素;(共享)
console.log(dog.arr);                                      // 打印出 [],因为cat只改变了其私有的arr
console.log(dog.pArr);                                     // 打印出 ['xx'], 因为cat改变了与狗子(dog)共享的pArr
登录后复制

当然,原型属性为基本数据类型,则不会被共享
在构造函数中:为了属性(实例基本属性)的私有性、以及方法(实例引用属性)的复用、共享。我们提倡:
1、将属性封装在构造函数中
2、将方法定义在原型对象上

ES5继承方式

首先,我们定义一个Animal父类

function Animal(n) {                              
    this.name = n;                                          // 实例属性
    this.arr = [];                                          // 实例属性(引用类型)
    this.say = function(){                                  // 实例方法
        return 'hello world';
    }
}
Animal.prototype.sing = function() {                        // 追加原型方法  
    return '吹呀吹呀,我的骄傲放纵~~';
}
Animal.prototype.pArr = [];                                 // 追加原型属性(引用类型)
登录后复制

1、原型链继承

function Cat(n) {
    this.cName = n;
}
Cat.prototype = new Animal();                               // 父类的实例作为子类的原型对象

var tom = new Cat('tom');                                   // 此时Tom拥有Cat和Animal的所有实例和原型方法/属性,实现了继承
var black = new Cat('black');

tom.arr.push('Im tom');
console.log(black.arr);                                     // 打印出 ['Im tom'], 结果其方法变成了共享的,而不是每个实例所私有的,这是因为父类的实例方法/属性变成了子类的原型方法/属性了;
登录后复制

优点: 实现了子对象对父对象的实例 方法/属性 和 原型方法/属性 的继承;
缺点: 子类实例共享了父类构造函数的引用数据类型属性。

2、借用构造函数

function Cat(n) {
    this.cName = n;                     
    Animal.call(this, this.cName);                           // 核心,把父类的实例方法属性指向子类
}

var tom = new Cat('tom');                                    // 此时Tom拥有Cat和Animal的所有实例和原型方法/属性,实现了继承
var black = new Cat('black');

tom.arr.push('Im tom');
console.log(black.arr);                                      // 打印出 [], 其方法和属性是每个子类实例所私有的;
tom.sing();                                                  // undefind 无法继承父类的原型属性及方法;
登录后复制

优点:
1、实现了子对象对父对象的实例 方法/属性 的继承,每个子类实例所继承的父类实例方法和属性都是其私有的;
2、 创建子类实例,可以向父类构造函数传参数;
缺点: 子类实例不能继承父类的构造属性和方法;

3、组合继承

function Cat(n) {
this.cName = n;                     
    Animal.call(this, this.cName);                          // 核心,把父类的实例方法属性指向子类
}
Cat.prototype = new Parent()                                // 核心, 父类的实例作为子类的原型对象
Cat.prototype.constructor = Cat;                            // 修复子类Cat的构造器指向,防止原型链的混乱

tom.arr.push('Im tom');
console.log(black.arr);                                     // 打印出 [], 其方法和属性是每个子类实例所私有的;
tom.sing();                                                 // 打印出 '吹呀吹呀,我的骄傲放纵~~'; 子类继承了父类的原型方法及属性
登录后复制

优点:
1、创建子类实例,可以向父类构造函数传参数;
2、父类的实例方法定义在父类的原型对象上,可以实现方法复用;
3、不共享父类的构造方法及属性;
缺点: 调用了2次父类的构造方法

4、寄生组合继承

function Cat(n) {
this.cName = n;                     
    Animal.call(this, this.cName);                          // 核心,把父类的实例方法属性指向子类
}
Cat.prototype = Parent.prototype;                           // 核心, 将父类原型赋值给子类原型(子类原型和父类原型,实质上是同一个)
Cat.prototype.constructor = Cat;                            // 修复子类Cat的构造器指向,防止原型链的混乱

tom.arr.push('Im tom');
console.log(black.arr);                                     // 打印出 [], 其方法和属性是每个子类实例所私有的;
tom.sing();                                                 // 打印出 '吹呀吹呀,我的骄傲放纵~~'; 子类继承了父类的原型方法及属性
tom.pArr.push('publish');                                   // 修改继承于父类原型属性值 pArr;
console.log(black.pArr);                                    // 打印出 ['publish'], 父类的原型属性/方法 依旧是共享的,
// 至此简直是完美呀~~~ 然鹅!
Cat.prototype.childrenProp = '我是子类的原型属性!';
var parent = new Animal('父类');
console.log(parent.childrenProp);                           // 打印出'我是子类的原型属性!' what? 父类实例化的对象拥有子类的原型属性/方法,这是因为父类和子类使用了同一个原型
登录后复制

优点:
1、创建子类实例,可以向父类构造函数传参数;
2、子类的实例不共享父类的构造方法及属性;
3、只调用了1次父类的构造方法;
缺点: 父类和子类使用了同一个原型,导致子类的原型修改会影响父类;

5、寄生组合继承(简直完美)

function Cat(n) {
this.cName = n;                     
    Animal.call(this, this.cName);                          // 核心,把父类的实例方法属性指向子类;
}
var F = function(){};                                       // 核心,利用空对象作为中介;
F.prototype = Parent.prototype;                             // 核心,将父类的原型赋值给空对象F;
Cat.prototype = new F();                                    // 核心,将F的实例赋值给子类;
Cat.prototype.constructor = Cat;                            // 修复子类Cat的构造器指向,防止原型链的混乱;
tom.arr.push('Im tom');
console.log(black.arr);                                     // 打印出 [], 其方法和属性是每个子类实例所私有的;
tom.sing();                                                 // 打印出 '吹呀吹呀,我的骄傲放纵~~'; 子类继承了父类的原型方法及属性;
tom.pArr.push('publish');                                   // 修改继承于父类原型属性值 pArr;
console.log(black.pArr);                                    // 打印出 ['publish'], 父类的原型属性/方法 依旧是共享的;
Cat.prototype.childrenProp = '我是子类的原型属性!';
var parent = new Animal('父类');
console.log(parent.childrenProp);                           // undefind  父类实例化的对象不拥有子类的原型属性/方法;
登录后复制

优点: 完美实现继承;
缺点:实现相对复杂

附YUI库实现继承

function extend(Child, Parent) {
    var F = function(){};
    F.prototype = Parent.prototype;
    hild.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype;                          
}
// 使用
extend(Cat,Animal);
登录后复制

Child.uber = Parent.prototype; 的意思是为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。(uber是一个德语词,意思是"向上"、"上一层"。)这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。

ES6继承方式

class Animal{                                                // 父类
    constructor(name){                                       // 构造函数
        this.name=name;
    }
    eat(){                                                   // 实例方法
        return 'hello world';
    }
}
class Cat extends Animal{                                    // 子类
  constructor(name){
      super(name);                                           // 调用实现父类的构造函数
      this.pName = name;            
  }
  sing(){
     return '吹呀吹呀,我的骄傲放纵~~';
  }
}
登录后复制

apache php mysql

相关文章

php构造函数的继承方法,php构造函数继承

JavaScript 原型继承之构造函数继承

相关视频:

极客学院PHP面向对象视频教程

以上是js构造函数是什么?详解构造函数继承方法及优缺点的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统 如何使用WebSocket和JavaScript实现在线语音识别系统 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术 WebSocket与JavaScript:实现实时监控系统的关键技术 Dec 17, 2023 pm 05:30 PM

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何使用WebSocket和JavaScript实现在线预约系统 如何使用WebSocket和JavaScript实现在线预约系统 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

如何利用JavaScript和WebSocket实现实时在线点餐系统 如何利用JavaScript和WebSocket实现实时在线点餐系统 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

JavaScript和WebSocket:打造高效的实时天气预报系统 JavaScript和WebSocket:打造高效的实时天气预报系统 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

简易JavaScript教程:获取HTTP状态码的方法 简易JavaScript教程:获取HTTP状态码的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

javascript中如何使用insertBefore javascript中如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用于在DOM树中插入一个新的节点。这个方法需要两个参数:要插入的新节点和参考节点(即新节点将要被插入的位置的节点)。

如何在JavaScript中获取HTTP状态码的简单方法 如何在JavaScript中获取HTTP状态码的简单方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP状态码获取方法简介:在进行前端开发中,我们常常需要处理与后端接口的交互,而HTTP状态码就是其中非常重要的一部分。了解和获取HTTP状态码有助于我们更好地处理接口返回的数据。本文将介绍使用JavaScript获取HTTP状态码的方法,并提供具体代码示例。一、什么是HTTP状态码HTTP状态码是指当浏览器向服务器发起请求时,服务

See all articles