js中面向对象的介绍
什么是物体
让我们先来看看立面3中对象是如何定义的
无序属性的集合,其属性可以包括基本值、对象或函数。对象是一组没有特定顺序的值。对象的每个属性或方法都有一个俄语名称,每个名称都映射到一个值。
简单理解对象是由属性和方法组成的
面向对象的特性
密封和包装
对于一些功能相同或相似的代码,我们可以把它们放入一个函数中。当我们多次使用这个函数时,我们只需要调用它,而不需要多次重写它。
这里我们可以理解创建对象的几种模式:单例模式、工厂模式、构造器模式、原型模式等等。
继承
子类可以继承父类的属性和方法
多态性(重载和覆盖)
重载:严格来说js中没有重载函数,但是我们可以通过判断函数的不同参数来实现不同的函数来模拟重载。覆盖:子类可以覆盖父类的属性和方法在javascript中的封装
单一模式
小王在一个小公司,有自己的前端,所以他这样写js
var a=1;函数GetNum(){ return 1;}后来公司又招了另一个前端小明,于是就变成了两个人一起写同一个js。有一天,小王发现自己写的getNum方法有问题。原来小华写的js里面也有一个getNum函数。代码合并后,他覆盖了,所以他去找小华的理论。经过一番妥协,两人都修改了自己的代码。
var小明={ num:1,getnum 3360 function(){ return 1;} } var xiaohua={ num:2,getnum 3360 function(){ return 2;}}这就是我们所说的单例模式(命名空间)
我们把描述同一事物的方法或属性放在同一个对象中,不同事物的方法或属性如果名称相同,就不会相互冲突。
单一模式的优缺点
1.使用单一模式,我们可以实现简单的模块化开发
varutils={ getcss : function(){//code }、getbyclass : function(){//code }、setcss:function () {//code}}我们可以将自己编写的工具和方法放入单独的js文件中,直接导入。
2.避免全局变量名的冲突
需要注意的是,我们在介绍每个模块的时候,需要注意介绍的顺序,是根据每个模块之间的相互依赖关系来安排的;
3.缺点:
Singleton模式只是在一定程度上避免了变量名的冲突,但并不能完全解决这个问题。而且,在不同的对象下,我们可能会有很多功能相同的代码,最终导致大量的冗余代码。Singleton模式让每个对象都有自己独立的名称空间,但是它不能大规模生产。每个新对象都必须用相同的代码重写。Var person1={name:' Xiaoming ',age:24,showname 3360 function(){ console . log('我的名字是:' this . name)} };Var person1={name:' Xiaohua ',age:25,showname 3360 function(){ console . log('我的名字是:' this . name)} };工厂模式
1.工厂模式其实就是在一个函数中创建需要一个一个写的对象,说白了就是普通函数的封装。
2.工厂模式由3个步骤组成:
1)引入原材料-创建空对象
2)加工原材料-加工对象:给对象增加属性和方法;
3)输出产品-退货对象:退货对象;
函数CreatePerson(姓名、年龄){ var obj={ };//1.创建一个空对象//2。机器对象obj.name=name年龄=年龄;obj . show name=function(){ console . log('我的名字是:' this . name)};返回对象;//3.输出对象;}var person1=CreatePerson('小明',23)var person2=CreatePerson('小华',23)person 1 . show name();//我叫:小明person 2 . show name();//我叫:小华工厂模式的优缺点
既然叫工厂模式,就跟我们身边的工厂一样。我们只需要投入原材料就能得到我们需要的产品。
工厂模式也解决了单件模式下的大规模生产问题,避免了单件模式下的大量冗余代码,封装了系统,提高了代码的复用率
然而,工厂模式不同于js内置类的调用方法
构造函数模式
您可以创建自定义类,也可以创建新实例。构造函数处理的是类和实例。//构造函数:首字母大写(约定成立);函数create person(姓名、年龄){//创建一个自定义类。//这在构造函数中是所有新的实例。//构造函数存储私有属性和方法。this.name=namethis.age=年龄;this . show name=function(){ console . log('我的名字是:' this . name)}//示例1 var person 1=new CreatePerson(' Xiaoming ',25) //示例2 var person 2=new CreatePerson(' Xiaohua ',24)下面我们来说说工厂模式和构造器模式的区别
1.通话时不同:
工厂模式:调用时只是普通函数createPerson()的调用;
构造函数模式:new create person();
2.功能体不同:
工厂模式有三个步骤:1)创建对象2)处理对象3)返回对象;
构造器模式只有一个步骤:只有被处理的对象;因为默认情况下系统会创建对象并为其返回对象;
3.默认情况下,构造函数会向我们返回一个对象,如果我们必须手动返回它:
(1)字符串类型手动返回:对以前实例上的属性和方法没有影响;
(2)手工返回实例上的属性和方法在引用数据类型:之前被覆盖;实例无法调用属性和方法;
构造函数的方法都是私有方法,每个实例调用自己的私有方法,也会有很多重复的代码。
我们可以使用原型模式在每个实例中用相同的方法解决函数问题
原型模式
函数CreatePerson(姓名、年龄){ this.name=namethis.age=年龄;}//我们把公共方法放在函数的原型链上,CreatePerson . prototype . show name=function(){ console . log('我叫:' this . name)} varperson 1=new CreatePerson(' Xiaoming ',25)var person 2=new CreatePerson(' Xiaohua ',24)person 1 . show name()//Xiaoming # # # # #原型模式的关键:
1)每个函数数据类型(普通函数、类)都有一个名为prototype的属性。
2)prototype天生具有一个名为constructor:的指向当前类的属性;
3)每个对象数据类型(普通对象、原型、实例)都有一个属性。
被调用的__proto__:指向当前实例所属类的原型;
这三句都懂了,就不用看下面的东西了。//手动滑稽
让我们通过例子来看看这些词是什么意思
函数CreatePerson(姓名、年龄){ this.name=namethis . age=age } create person . prototype . show name=function(){ console . log('我叫:' this . name)} varperson 1=new create person('小明',25岁);Console.dir(person1)显示在chrome浏览器控制台中
从图中可以看出,对象person1有两个属性,名字和年龄,person1的__proto__指向其构造函数的原型(CreatePerson),还有一个showName的方法。
其中一个是相关的:人1。_ _ proto _ _==create person . prototype。
那就看看吧
function Foo(){ this . a=1;} foo . prototype . a=2;foo . prototype . b=3;var f1=new Foo//如果没有参数,可以省略括号。console . log(f1 . a)//1 console . log(f1 . b)//3以此为例。当我们寻找f1.a时,因为f1有这个属性,我们得到f1 . a=1;当我们寻找f1.b时,f1中没有这样的属性,所以我们遵循f1的链条。__proto__在它的构造函数的原型上寻找它,所以我们得到f1 . b=3;
那么,Foo.prototype就是一个对象,那么它的_ _ prototype _ _指向哪里呢
记得刚才说的那句话吗
每个对象数据类型(普通对象、原型、实例)都有一个名为__proto__:的属性,该属性指向当前实例所属类的原型
此外,我们应该知道
每个对象都是构造函数object的一个实例
所以我们可以还原这个原型
等等,好像还有一个Object.prototype.__proto__指向null。这到底是什么?
我们理解Object.prototype是一个对象,所以它的__proto__指向它的构造函数的原型,最后找到它或者指向它自己,所以转过来好像没有意义,所以指向null,我们发现所有的对象都是由函数(构造函数)创建的,那么函数是谁创建的呢?从石头里?
在js中,函数是由构造函数创建的,每个函数都是函数的一个实例
现在我们基本上可以得到一个完整的原型地图
是不是有点乱?根据我们刚才说的,这个图可以拉直。这里应该注意的是,函数。__proto__指向它的原型
再多说一点,在判断数据类型的方法时,我们知道方法是有实例的
例如
乙的实例
判决的实例规则是:
沿着A的__proto__线和b的原型线看,如果两条线可以找到相同的引用(对象),那么返回true。如果发现端点不重合,则返回false。
让我们看看前面的例子
function Foo(){ this . a=1;} foo . prototype . a=2;foo . prototype . b=3;var f1=new Foo//如果没有参数,可以省略括号。console . log(f1.a)//1 console . log(f1 . b)//3当我们寻找f1 . a时,因为f1有这个属性,我们得到f1 . a=1;
当我们寻找f1.b时,f1中没有这样的属性,所以我们遵循f1的链条。__proto__在它的构造函数的原型上寻找它,所以我们得到f1 . b=3;
当我们寻找一个对象的属性时,我们首先在对象的私有空间中查找它。如果没有找到,我们将沿着对象的__proto__的链,沿着__proto__查找,直到找到Object.prototype,这个值是未定义的,称为原型链。
在网页中列出一些相关的原型链
感兴趣的学生可以看到我们常用的方法是通过浏览器控制台在哪个类上定义的,比如getelementsbytagname、addeventlistener等等
继承
这里我们主要讲组合继承(叫原型链)
函数父亲(){ this.xxx=80this.yyy=100this .饮品=函数(){ } }父亲. prototype.zzz=函数(){}var父亲=新父亲;函数Son(){ this . AAA=120;this.singing=function(){}父. call(this);}Son.prototype=新父亲;Son . prototype . constructor=Son;瓦尔松=新松康索迪尔(松)
这样写有一个不好的地方:子类的私有属性中有父类的私有属性,子类的公共属性中有父类的私有属性;
根据我们以前的知识,我们可以这样重写
函数父亲(){ this.xxx=80this.yyy=100this .饮品=函数(){ } }父亲. prototype.zzz=函数(){}var父亲=新父亲;函数Son(){ this . AAA=120;this.singing=function(){}父. call(this);//使用call} son继承父类的私有属性。原型。_ _原型_ _ _=父亲。原型var son=新的子控制台。迪尔(儿子)。最后,给出了一个思维导图
放大图片看不清就下载地址
以上就是本文的全部内容。希望本文的内容能给大家的学习或工作带来一些帮助,也希望多多支持我们!
版权声明:js中面向对象的介绍是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。