Js类的构建与继承案例详解


Posted in Javascript onSeptember 15, 2021

JS里类的定义和继承实在五花八门,所以单独开一个笔记本记录。

定义

派生于Object的方式

1.new Object:在创建对象后动态定义属性、方法
var Car = new Object;
Car.color = "red";
Car.showColor = function(){
	console.log(this.color);
}
//想要继承就要先构造空对象然后用__proto__原型链来继承
var Car1 = new Object; //或者 = {}
Car1.__proto__ =  Car;

使用函数构造

1.工厂函数:在函数内生成类,好处是不用再构造空对象+继承原型链,直接返回一个对象的复制,类似于构造函数
function createCar(){ //也可以为此函数传递参数creatCar(color)
	let car = new Object;
	car.color = "red"; //传递参数:car.color = color
	car.showColor = function(){
		console.log(this.color);
	}
	return car;
}

var newCar = createCar(); //传递参数:createCar("red")
//但是使用工厂函数,每构造一个函数就会构建一次showColor方法,很不划算
//所以可以在类的工厂函数之前为所有类统一确定一个用于继承的方法
function showColor(){
	console.log(this.color);
}
function createCar(){
...
	car.showColor = showColor;
...
}

2.构造函数方法:类似于工厂函数方法,使用构造函数方法。不同的是构造函数内属性只能为this.attr
function Car(color,num){
	this.color = color;
	this.num = num;
	this.showColor = function(){
		console.log(this.color);
	}
	this.drivers = new Array("mike");
}
var car1 = new Car("red",1); //注意,此时Car本身的属性和方法不能被访问,只能实例化之						 后访问
					 //比如:console.log(new Car("red",1).color)
					 //这表示,构造函数真的是类似类的构造函数而非实例化对象,js也					  //有传统意义的对象而不是只有函数对象
//和方式1一样Car的类内函数showColor将在每次构造时被构造出来,占据了没必要的空间
var car2 = new Car("green",1);
car1.drivers.push("kiki");
console.log(car2.drivers); //不存在引用同一个数组的现象

3.原型方法:类似于Object派生,形成基于Object的原型链,再绑定方法和属性
function Car(){};
Car.prototype.color = "red";
Car.prototype.showColor = function(){
		console.log(this.color);
}
//Car.prototyoe = { //把多个绑定的函数放进一个匿名的类来写
//	mathod1:function(){...};
//	mathod2:function(){...};
//}
Car.prototype.drivers = new Array("mike","jhon");
var car1 = new Car(); //一定要创建实例才能调用方法访问属性
var car2 = new Car();
car1.drivers.push("bill");
console.log(car1.color);
console.log(car2.drivers);
//这样绑定arry的属性全部都指向同一个数组对象,属于引用。当改变一个实例的color,所有的color都一起变了

混合方法:

1.构造函数+原型:构造函数内只构造属性和类内数组,而用原型的方式声明类内函数
function Car(color){
	this.color = color;
	this.drivers = new Array("mike");
}
Car.prototype.showColor = function(){
	console.log(this.color);
}
var car1 = new Car(); //一定要创建实例才能调用方法访问属性
var car2 = new Car();
car1.drivers.push("bill");
console.log(car2.drivers); //避免了原型方法的缺点

2.使用class关键字定义类:不能在类外直接定义属性,仍需要使用prototype方法在类外绑定函数对象。
class Car{
           constructor(color) {
                this.color = color;
           }
           drivers = new Array("mike","jhon");
           hello = function(){
           		return "Di Di"+ this.color; 
           }
           
        }

Car.prototype.hello = function (){ //类外绑定方法
            return "Di Di";
}

var car1 = new Car("red");
var car2 = new Car("green");
car1.drivers.push("kiki");
console.log(car1.color);
console.log(car2.hello());

综上,当在类内定义变量时,在构造实例时会随之一起调用构造函数进行构造,而类外绑定的方法、属性将会是一种引用的形式不参与构造直接调用。同时,也便于保密,隐藏信息。

继承

1.伪装继承:把类作为新类的构造函数来继承,有点神奇,js里类可以当成函数对象的奇特属性
function Car1(color){
	this.color = color;
	this.showColor = function(){
		console.log("this car is "+this.color);
	}
	this.drivers = new Array("mike");
}

function Car2(){
	this.makeSound = function(){
		console.log("Di Di");
	}
}

function Car3(color){
	this.newConstruct = Car1; //作为构造函数传入
	this.newConstruct(color); //调用构造函数
	delete this.newConstruct;
	this.newConstruct2 = Car2; //多重继承,但是由于闭包机制,要用不同的构造函数名
	this.newConstruct2(); 
	delete this.newConstruct2;
}//同样,伪装继承也可以用.prototype来绑定构造函数

var car1 = new Car3("red");
var car2 = new Car3("green");
car1.drivers.push("kiki");
console.log(car1.color);
car1.showColor();
car1.makeSound();
console.log(car2.drivers);

2.用父类的方法call和apply进行继承
function Car1(color){
	this.color = color;
	this.showColor = function(){
		console.log("this car is"+this.color);
	}
}
function Car2(num){
	this.num = num;
	this.makeSound = function(){
		console.log("Di Di");
	}
}

function Car3(color,num){
	Car1.call(this, color);
	Car2.apply(this, augments);//augments为一个数组,包含所需的参数
}

var car1 = new Car3("red",1);
var car2 = new Car3("green",2);
console.log(car1.color);
console.log(car2.num);
car1.showColor();
car1.makeSound();

//也可以把.apply和.call写在类外,但只能对实例进行操作,不能用于构成类

3.用原型链进行继承:使用__proto__和.prototype构成原型链,缺点是不能实现多重继承,只能通过绑定成构造函数或者再创造几个类用链式方式继承来来实现多重继承
function Car1(color){
	this.color = color;
	this.showColor = function(){
		console.log("this car is"+this.color);
	}
}
function Car3(){};
Car3.prototype = new Car1();

4.用class...extends...,也可以实现继承,但是不能实现多重继承,也只能像原型链一样用多个类作为节点的方式来实现多重继承,属于是ES6的特性了。ES6还引入了let、public、private、protected关键字但是不能实现多重继承,也没有什么包的概念也是挺奇葩的
class Car2 extends Car1{
           constructor(color) {
                super(); //类似java,super本身可以代表父类,此处是用了代表父类的
                		 //构造函数
                this.color = color;
           }
           drivers = new Array("mike","jhon");
           hello = function(){
           		return "Di Di"+ this.color; 
           }  
        }

5.使用参数可变的封装函数extend(需要自己实现)实现多个类的按顺序继承extend(A,B,C)的链式继承,B节点继承A,C继承B(实际上还是链式方式,但是封装了好理解,是知乎大佬晓宏和csdn大佬浴盆的答案,https://blog.csdn.net/sysuzhyupeng/article/details/54846949知乎那个写法不容易理解)。主要还是利用类可以为函数并可作为返回值的特性

所以,正常情况下:创建类用class或者构造函数+原型的方式;继承类用class...extends...或者call方法。了解工厂方法和伪装继承。

重载就不细究了,和class一样不完善,只能自己用augments.length去实现。

 

到此这篇关于Js类的构建与继承案例详解的文章就介绍到这了,更多相关Js类的构建与继承内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript jQuery $.post $.ajax用法
Jul 09 Javascript
JavaScript 闭包在封装函数时的简单分析
Nov 28 Javascript
jQuery dialog 异步调用ashx,webservice数据的代码
Aug 03 Javascript
精通Javascript系列之数值计算
Jun 07 Javascript
JavaScript实现随机替换图片的方法
Apr 16 Javascript
浅谈jquery中ajax跨域提交的时候会有2次请求的问题
Nov 10 jQuery
vue项目打包部署到服务器的方法示例
Aug 27 Javascript
JavaScript时间日期操作实例小结【5个示例】
Dec 22 Javascript
jquery操作select常见方法大全【7种情况】
May 28 jQuery
Vue2.0 实现页面缓存和不缓存的方式
Nov 12 Javascript
Vue如何基于vue-i18n实现多国语言兼容
Jul 17 Javascript
vue 实现弹窗关闭后刷新效果
Apr 08 Vue.js
JavaScript 数组去重详解
Sep 15 #Javascript
5种方法告诉你如何使JavaScript 代码库更干净
Sep 15 #Javascript
JavaScript小技巧带你提升你的代码技能
Sep 15 #Javascript
javascript函数式编程基础
Sep 15 #Javascript
15个值得收藏的JavaScript函数
Sep 15 #Javascript
详解JavaScript中Arguments对象用途
详细谈谈JavaScript中循环之间的差异
Aug 23 #Javascript
You might like
PHP微信分享开发详解
2017/01/14 PHP
PHP-FPM 的管理和配置详解
2019/02/17 PHP
CentOS7系统搭建LAMP及更新PHP版本操作详解
2020/03/26 PHP
css3实现背景模糊的三种方式
2021/03/09 HTML / CSS
javascript div 弹出可拖动窗口
2009/02/26 Javascript
一段批量给页面上的控件赋值js
2010/06/19 Javascript
jQuery+CSS 半开折叠效果原理及代码(自写)
2013/03/04 Javascript
hover的用法及live的用法介绍(鼠标悬停效果)
2013/03/29 Javascript
jquery重新播放css动画所遇问题解决
2013/08/21 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
2015/05/25 Javascript
JS与jQuery实现隔行变色的方法
2016/09/09 Javascript
使用Vue-Router 2实现路由功能实例详解
2017/11/14 Javascript
windows下更新npm和node的方法
2017/11/30 Javascript
vue实现的微信机器人聊天功能案例【附源码下载】
2019/02/18 Javascript
websocket4.0+typescript 实现热更新的方法
2019/08/14 Javascript
element-ui table行点击获取行索引(index)并利用索引更换行顺序
2020/02/27 Javascript
基于javascript处理二进制图片流过程详解
2020/06/08 Javascript
python概率计算器实例分析
2015/03/25 Python
在Django的URLconf中进行函数导入的方法
2015/07/18 Python
解决tensorflow添加ptb库的问题
2020/02/10 Python
Python批量启动多线程代码实例
2020/02/18 Python
pytorch使用tensorboardX进行loss可视化实例
2020/02/24 Python
如何基于Python代码实现高精度免费OCR工具
2020/06/18 Python
keras用auc做metrics以及早停实例
2020/07/02 Python
新西兰最大的天然保健及护肤品网站:HealthPost(直邮中国)
2021/02/13 全球购物
餐饮主管岗位职责
2013/12/10 职场文书
数学与统计学院学生个人职业生涯规划书
2014/02/10 职场文书
优秀的2014年两会精神解读
2014/03/17 职场文书
抽奖活动主持词
2014/03/31 职场文书
ktv筹备计划书
2014/05/03 职场文书
助人为乐好少年事迹材料
2014/08/18 职场文书
故宫的导游词
2015/01/31 职场文书
会计工作态度自我评价
2015/03/06 职场文书
会议简讯范文
2015/07/20 职场文书
MySQL安装后默认自带数据库的作用详解
2021/04/27 MySQL
新手初学Java网络编程
2021/07/07 Java/Android