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 相关文章推荐
js玩一玩WSH吧
Feb 23 Javascript
JavaScript访问样式表代码
Oct 15 Javascript
JS实现匀速运动的代码实例
Nov 29 Javascript
Js Jquery创建一个弹出层可加载一个页面
May 08 Javascript
javascript表单验证和Window详解
Dec 11 Javascript
jquery动态遍历Json对象的属性和值的方法
Jul 27 Javascript
weUI应用之JS常用信息提示弹层的封装
Nov 21 Javascript
详解webpack 入门总结和实践(按需异步加载,css单独打包,生成多个入口文件)
Jun 20 Javascript
微信小程序 空白页重定向解决办法
Jun 27 Javascript
基于webpack-hot-middleware热加载相关错误的解决方法
Feb 22 Javascript
从零搭一个自用的前端脚手架的方法步骤
Sep 23 Javascript
详解JavaScript中的执行上下文及调用堆栈
Apr 29 Javascript
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
星际争霸任务指南——虫族
2020/03/04 星际争霸
PHP去掉从word直接粘贴过来的没有用格式的函数
2012/10/29 PHP
php中替换字符串中的空格为逗号','的方法
2014/06/09 PHP
php实现事件监听与触发的方法
2014/11/21 PHP
PHP导出带样式的Excel示例代码
2016/08/28 PHP
phpQuery采集网页实现代码实例
2020/04/02 PHP
Javascript 获取链接(url)参数的方法[正则与截取字符串]
2010/02/09 Javascript
jQuery 核心函数以及jQuery对象
2010/03/23 Javascript
2014 年最热门的21款JavaScript框架推荐
2014/12/25 Javascript
jquery判断当前浏览器的实现代码
2015/11/07 Javascript
JS获取鼠标坐标位置实例分析
2016/01/20 Javascript
JavaScript中文件上传API详解
2016/04/01 Javascript
JavaScript面试题大全(推荐)
2016/09/22 Javascript
基于JS组件实现拖动滑块验证功能(代码分享)
2016/11/18 Javascript
Nodejs 搭建简单的Web服务器详解及实例
2016/11/30 NodeJs
javascript实现文字无缝滚动效果
2017/08/26 Javascript
用Webpack构建Vue项目的实践
2017/11/07 Javascript
JS实现瀑布流效果
2020/03/07 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
[36:22]VP vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
利用Python绘制数据的瀑布图的教程
2015/04/07 Python
Python合并字典键值并去除重复元素的实例
2016/12/18 Python
Python Web编程之WSGI协议简介
2018/07/18 Python
Python random模块制作简易的四位数验证码
2020/02/01 Python
基于Python pyecharts实现多种图例代码解析
2020/08/10 Python
实例教程 纯CSS3打造非常炫的加载动画效果
2014/11/05 HTML / CSS
HTML5 audio标签使用js进行播放控制实例
2015/04/24 HTML / CSS
HTML5在线预览PDF的示例代码
2017/09/14 HTML / CSS
自我评价格式
2014/01/06 职场文书
工程采购员岗位职责
2014/03/09 职场文书
2014年残联工作总结
2014/11/21 职场文书
会议接待欢迎词范文
2015/01/26 职场文书
民主评议党员个人自我评价
2015/03/03 职场文书
2016年师德先进个人事迹材料
2016/02/29 职场文书
2016年“11.11”光棍节活动总结
2016/04/05 职场文书
Python内置的数据类型及使用方法
2022/04/13 Python