深入解读 Js 中的面向对象编程
前言:今天看了一篇文章觉得很不错,所以给大家分享一下,也许很多人都看过面向对象编程甚至写过这样博客,觉得面向对象编程就那样,没啥好说的,那可能是因为你对这方面知识已经了解,可以选择性跳过。那如果有更通俗易懂的解读欢迎分享给我。或者有更好的学习技术书籍推荐也可以在评论下方留言,谢谢。
面向对象的几个概念
在进行面向对象编程,首先了解传统的面向对象编程(例如Java)中常会涉及到的概念,大致可以包括:
- 类:定义对象的特征。它是对象的属性和方法的模板定义。
- 对象(或称实例):类的一个实例。
- 属性:对象的特征,比如颜色、尺寸、大小等。
- 方法:对象的行为,比如走路、说话等。
- 构造函数:对象初始化的瞬间被调用的方法。
- 继承:子类可以继承父类的特征。例如,猫继承了动物的一般特性。
- 封装:一种把数据和相关的方法绑定在一起使用的方法。
- 抽象:结合复杂的继承、方法、属性的对象能够模拟现实的模型。
- 多态:不同的类可以定义相同的方法或属性。
在 JavaScript 的面向对象编程中大体也包括这些。不过在称呼上可能稍有不同,例如,JavaScript 中没有原生的“类”的概念,
而只有对象的概念。因此,随着你认识的深入,我们会混用对象、实例、构造函数等概念。
对象的创建
在js里,我们通常可以使用构造函数来创建特定类型的对象。诸如 Object 和 Array 这样的原生构造函数。此外,我们也可以创建自定义的构造函数。例如:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
var person1 = new Person('Excellent', 18, 'Student');
var person2 = new Person('wangli', 20, 'Doctor');
构造函数应该以一个大写字母开头(和Java中定义的类一样),普通函数则小写字母开头。
要创建 Person
的新实例,必须使用 new
操作符。
以这种方式调用构造函数实际上会经历以下4个步骤:
- 创建一个新对象(实例)
- 将构造函数的作用域赋给新对象(也就是重设了
this
的指向,this
就指向了这个新对象) - 执行构造函数中的代码(为这个新对象添加属性)
- 返回新对象
在上面的例子中,我们创建了 Person
的两个实例 person1
和 person2
。
原型模式定义对象的方法
//创建面向对象
function Person(age,name,job){
this.name=name;
this.age=age;
this.job=job;
}
Person.prototype.sayName = function () {
console.log(this.name);
/*Person.prototype={
constructor:Person,// 这里重新将构造函数指回Person构造函数
sayname:function(){
console.log(this.name);
}
}*///也可以这样定义
var person1=new Person("38","黎明","明星");
var person2=new Person("18","Excellent","前端开发");
console.log(person1.sayname===person2.sayname);//true
person1.sayname();//黎明
person2.sayname();//Excellent
通过原型模式定义的方法sayName()
为所有的实例所共享。也就是,person1
和person2
访问的是同一个sayName()
函数。同样的,公共属性也可以使用原型模式进行定义:
function Chinese (name) {
this.name = name;
}
Chinese.prototype.shcool= '实验中学'; // 公共属性,所有实例共享
组合使用构造函数模式和原型模式
创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,
而原型模式用于定义方法和共享的属性。
继承
大多的面向对象语言都支持两种继承方式:接口继承和实现继承。ECMAScript只支持实现继承,而且其实现继承主要依靠原型链来实现。
原型链继承
使用原型链作为实现继承的基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。首先我们先回顾一些基本概念:
- 每个构造函数都有一个原型对象(
prototype
) - 原型对象包含一个指向构造函数的指针(
constructor
) - 实例都包含一个指向原型对象的内部指针(
[[Prototype]]
)
如果我们让原型对象等于另一个类型的实现,结果会怎么样?显然,此时的原型对象将包含一个指向另一个原型的指针,
相应的,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,
如此层层递进,就构成了实例与原型的链条。可参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
简单的例子,演示了使用原型链实现继承的基本框架:
//原型继承
function Father(name){
this.name=name;
}
Father.prototype.sayfname=function(){
console.log(this.name);
}
function Child(cname){
this.cname=cname;
}
Child.prototype=new Father('父级');//继承父级Father
Child.prototype.constructor=Child;
//会切断原型链,导致无法进行继承,变成 Child -> Object
/*Child.prototype={
saycname:function(){
console.log(this.cname);
}
}*/
Child.prototype.saycname=function(){
console.log(this.cname);
}
var child1=new Child('子级');
child1.saycname();
child1.sayfname();
原型链继承的核心语句是Child.prototype = new Father(
'父级');
,它实现了
Child
对Father
的继承,
而继承是通过创建Father
的实例,并将该实例赋给Child.prototype
实现的。
ps:原型链的问题:
1.首先是顺序,一定要先继承父类,然后为子类添加新方法。
2.其次,使用原型链实现继承时,不能使用对象字面量创建原型方法。因为这样做就会重写原型链.如上面注释一样。
借用构造函数继承
借用构造函数(constructor stealing)的基本思想如下:即在子类构造函数的内部调用超类型构造函数。
//构造函数
function Parent(name){
this.name=name;
this.colors=['blue','pink','yellow']
}
function Childs(name){
Parent.call(this,name);
}
var instance1 =new Childs('Excellent');
instance1.colors.push('black');
console.log(instance1.colors); // [ 'blue', 'pink', 'yellow', 'black' ]
console.log(instance1.name); // Excellent
var instance2 = new Childs("wangli");
console.log(instance2.colors); // ['blue','pink','yellow']
console.log(instance2.name); // wangli
缺点:同构造函数一样,无法实现方法的复用(所有的方法会被重复创建一份)
组合使用原型链和借用构造函数,混合模式
我们会组合使用原型链继承和借用构造函数来实现继承。也就是说,使用原型链实现对原型属性和方法的继承,
而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。
//组合使用原型链和借用构造函数
// 父类构造函数
function Person1(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
// 父类方法
Person1.prototype.saypname=function(){
console.log(this.name);
}
// 子类构造函数
function Student(name,age,job,school){
Person1.call(this,name,age,job);//继承父级的属性
this.school=school;
}
//createObject()对传入其中的对象执行了一次浅复制。
function createObject(proto) {
function F() { }
F.prototype = proto;
return new F();
}
// 继承父类的原型方法(获得父类原型链上的方法)
Student.prototype = createObject(Person1.prototype);
Student.prototype.constructor=Student;// 设置 constructor 属性指向 Student
// 子类方法
Student.prototype.sayschool=function(){
console.log(this.school);
}
var person1 = new Person1('wangli', 27, 'Student');
var student1=new Student('Lili','16','学生','第一实验中学');
var student2=new Student('Excellent','17','学生','第二实验中学');
person1.saypname();//wangli
student1.saypname();//Lili
student1.sayschool();//第一实验中学
student2.saypname();//Excellent
我们用些更简单的东西去解决,比如ES6中的面向对象语法
S6中引入了一套新的关键字用来实现class。
但它并不是映入了一种新的面向对象继承模式。JavaScript仍然是基于原型的,这些新的关键字包括class、
constructor、
static、
extends、
和super。
class
关键字不过是提供了一种在本文中所讨论的基于原型模式和构造器模式的面向对象的继承方式的语法糖(syntactic sugar)。
前面继承修改
//ES6 class关键字 面向对象的继承方式的语法糖(syntactic sugar)。
"user strict";
class Person2{
constructor(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
sayName(){
console.log(this.name);
}
}
class Student2 extends Person2{
constructor(name,age,job,school){
super(name,age,job,"Studen2");
this.school=school;
}
saySchool(){
console.log(this.school);
}
}
var stu1 = new Student2('weiwei', 20,'学生','Southeast University');
var stu2 = new Student2('lily', 22, '学生','Nanjing University');
stu1.sayName(); // weiwei
stu1.saySchool(); // Southeast University
stu2.sayName(); // lily
stu2.saySchool(); // Nanjing University
如果还有不太了解ES6的,可以看看阮一峰Es6入门:http://es6.ruanyifeng.com/
了解更多js知识,也可以到这里看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
深入解读 Js 中的面向对象编程的更多相关文章
- Day046--JavaScript-- DOM操作, js中的面向对象, 定时
一. DOM的操作(创建,追加,删除) parentNode 获取父级标签 nextElementSibling 获取下一个兄弟节点 children 获取所有的子标签 <!DOCTYPEhtm ...
- 前端 ---JS中的面向对象
JS中的面向对象 创建对象的几种常用方式 1.使用Object或对象字面量创建对象 2.工厂模式创建对象 3.构造函数模式创建对象 4.原型模式创建对象 1.使用Object或对象字面量创建对象 ...
- python 全栈开发,Day52(关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列)
昨日作业讲解: 京东购物车 京东购物车效果: 实现原理: 用2个盒子,就可以完整效果. 先让上面的小盒子向下移动1px,此时就出现了压盖效果.小盒子设置z-index压盖大盒子,将小盒子的下边框去掉, ...
- 前端JavaScript(3)-关于DOM操作的相关案例,JS中的面向对象、定时器、BOM、位置信息
小例子: 京东购物车 京东购物车效果: 实现原理: 用2个盒子,就可以完整效果. 先让上面的小盒子向下移动1px,此时就出现了压盖效果.小盒子设置z-index压盖大盒子,将小盒子的下边框去掉,就可以 ...
- 《JS中的面向对象技术》
内容要点: 1.什么是对象:JS权威指南学习总结-第六章 ,(有句话:一切都是对象) 2.什么面向对象 使用对象时,只关注对象提供的功能,不关注其内部细节,比如jQuery.面向对象是一种通用思想,并 ...
- 洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程
声明:本篇文章仅仅以游戏<绝地求生>作为一个参考话题来介绍面向对象编程,只是作为学术引用,其制作的非常简易的程序也不会作为商业用途,与蓝洞公司无关. <绝地求生>最近很火,笼络 ...
- JavaScript中的面向对象编程,详解原型对象及prototype,constructor,proto,内含面向对象编程详细案例(烟花案例)
面向对象编程: 面向:以什么为主,基于什么模式 对象:由键值对组成,可以用来描述事物,存储数据的一种数据格式 编程:使用代码解决需求 面向过程编程: 按照我们分析好的步骤,按步 ...
- 深入理解javascript中实现面向对象编程方法
介绍Javascript中面向对象编程思想之前,需要对以下几个概念有了解: 1. 浅拷贝和深拷贝:程序在运行过程中使用的变量有在栈上的变量和在堆上的变量,在对象或者变量的赋值操作过程中,大多数情况先是 ...
- python中的面向对象编程
在python中几乎可以完成C++里所有面向对象编程的元素. 继承:python支持多继承: class Derived(base1, base2, base3): pass 多态:python中的所 ...
随机推荐
- 吐槽版︱MRO-Microsoft R Open快捷键+界面识别+功能设置
下载了之后,发现连运行(RUN键)在哪都不知道,蒙逼的在哪倒弄半天,都执行不了...问了别人,都说"ctrl+enter",但是我的电脑执行不了,于是今天就狠狠的一个一个按钮的点一 ...
- HighCharts之2D颜色阶梯饼图
HighCharts之2D颜色阶梯饼图 1.实例源码 PieGradient.html: <!DOCTYPE html> <html> <head> <met ...
- sea.js介绍
网址:http://seajs.org/docs/ SeaJS是一个遵循CommonJS规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制.与jQuery等Ja ...
- org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir
1.错误描述 org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir svn: Co ...
- dijit.byId("grid") is undefined
1.错误描述 TypeError:dijit.byId(...) is undefined (68 out of range 3) 2.错误原因 var gridName = dijit ...
- 芝麻HTTP:TXT文本存储
将数据保存到TXT文本的操作非常简单,而且TXT文本几乎兼容任何平台,但是这有个缺点,那就是不利于检索.所以如果对检索和数据结构要求不高,追求方便第一的话,可以采用TXT文本存储.本节中,我们就来看下 ...
- JDBCTemplate简化JDBC的操作(二)
一.Spring对不同的持久化支持: Spring为各种支持的持久化技术,都提供了简单操作的模板和回调 ORM持久化技术 模板类 JDBC org.springframework.jdbc.core. ...
- Postman教程——发送第一个请求
系列文章首发平台为果冻想个人博客.果冻想,是一个原创技术文章分享网站.在这里果冻会分享他的技术心得,技术得失,技术人生.我在果冻想等待你,也希望你能和我分享你的技术得与失,期待. 前言 过年在家,闲来 ...
- ArXiv最受欢迎开源深度学习框架榜单:TensorFlow第一,PyTorch第四
[导读]Kears作者François Chollet刚刚在Twitter贴出最近三个月在arXiv提到的深度学习框架,TensorFlow不出意外排名第一,Keras排名第二.随后是Caffe.Py ...
- 安卓中webview读取html,同时嵌入Flex的SWF,交互
安卓中webview读取html,同时嵌入Flex的SWF,交互 安卓activity与html交互很简单,用javascript接口即可,网上一堆的例子,基本上没多大问题. 在html里面嵌入swf ...