当前位置: 首页 > Web前端 > JavaScript

js设计模式(一)面向对象——封装

时间:2023-03-26 20:43:00 JavaScript

前言最近在看typescript,其中一个主要目的就是为vue3.x做准备。3.x版本,游雨溪使用typescript重写了底层。详情请参考[[翻译]尤雨西:Vue3.0计划-掘金](https://juejin.im/post/684490...)。在typescript中,几乎完全采用了ES6语法,最重要的是类的使用。学这个有点迷糊。什么?继承还能这么玩?什么publicprivate什么派生类???难道我之前学的是假js???于是回去重新整理,学习面向对象编程。本系列文章全部基于ES5语法规则。不要告诉我你为什么不直接使用ES6。ES6最终会被编译成ES5并运行。男孩只是一个前端菜鸟,对编??程的理解并不深刻。他只是一个代码搬运工。文中如有错误或误解,请指正,万分感谢。本系列将讲解面向对象的封装、继承、多态三大特性,从而更好地理解面向对象编程。面向过程编程和面向对象编程(OOP)面向过程编程就是分析解决问题所需要的步骤,然后用函数一步步实现这些步骤。使用时,可以一一调用。面向对象编程面向对象编程就是把你的需求抽象成一个对象,针对这个对象分析它的特性和动作。我们称这个对象为类对象。基础知识对象理解程序员经常拿对象开玩笑:没有对象?自己创造一个新的,你可以为所欲为。那么究竟什么是对象呢?js中有一句话,万物皆对象,对象就是一个集合,可以有属性和方法。一个人是一个物体。他有吃饭睡觉的属性,有打工赚钱的方法。一切都可以抽象为对象,但每个对象都有自己的属性和方法。什么是面向对象编程???在js中,有两种编程风格。面对过程式编程和面向对象编程,我们写轮播、动画、页面,大部分都是过程式编程(反正我目前就是在做这个)。对象的三大特性封装、继承、多态当一个对象被创建时,中间发生了什么|new关键字有什么作用(面试题)1.创建一个新对象,这个对象的类型是`object`2.设置this在构造函数中设置新对象的internal,accessibility和[[prototype]]属性(指的是prototype.construtor指向的构造函数)3.使用步骤1中新建的对象作为this的上下文4.如果函数没有返回对象,则返回this。原型和原型链原型JavaScript规定每个构造函数都有一个指向另一个对象的原型属性。我们可以直接在原型对象上定义所有对象实例需要共享的属性和方法。该对象的所有属性和方法都将归构造函数所有。Prototype是对象的内部属性,我们通常通过实例化对象的__proto__属性来访问它。原型对象中还有一个属性constructor,它对应于创建所有指向原型的实例的constructor原型链。当我们访问一个对象的属性或方法时,它会先在对象本身中寻找,如果存在就直接使用,如果没有找到,会在原型对象中查找,如果找到,则直接使用。如果没有,就去prototype的prototype查找,直到找到Object对象的prototype。Object对象的原型没有原型。如果仍未在Object原型中找到,则返回null。functionPerson(name,age){this.name=namethis.age=agethis.action=function(){alert('helloword')}}varp=newPerson('游鱼溪',18)//实例化Person对象console.log(p.name)//尤雨熙/*它们之间关系的构造函数的原型==实例化p.__proto__构造函数==构造函数原型的构造函数*/console.log(Person.prototype===p.__proto__)//trueconsole.log(Person.prototype.constructor===Person)//trueconsole.log(p.constructor===Person)//真人脸对象——封装什么是封装封装就是将客观事物封装成抽象类,隐藏属性和方法的实现细节,对外只暴露接口。换句话说,封装就是将属性和方法组合成一个类的过程,这个过程称为封装。对象封装的几种形式对象字面量优点:代码简单易懂缺点:创建多个对象会产生大量代码,编写麻烦,没有实例和原型的概念//createobjectvarPerson={name:"especiallyYuxi",age:"18",action:function(){alert('helloword!');}}Person.namePerson.action()//创建一个空对象,并为空对象添加方法属性varPerson={}Person.name='尤雨熙'Person.age=18Person.action=function(){alert('helloword!');}工厂模式对象字面量的形式在创建多个对象时会产生大量的代码,如果我们把创建一个新对象,添加对象属性,返回一个对象的过程放到这个函数中,我们每次我们需要创建对象时都可以调用该函数。functioncreatePerson(name,age){varperson=newObject();person.name=name;person.age=age;person.action=function(){alert('helloword!');};returnperson;}//生成实例varp=createPerson('游鱼溪',18);varp2=createPerson('袁一峰',20)console.log(p.name)p.action()优点:避免创建大量对象代码臃肿的缺点:p1和p2之间没有内在联系。所谓“构造器”其实就是一个普通的函数,只是内部使用了this变量。在构造函数上使用new运算符,可以生成实例,并将this变量绑定到实例对象。functionPerson(name,age){//通过这个方法添加属性this.name=namethis.age=agethis.action=function(){alert('helloword')}}//实例化对象varp1=newPerson('尤雨熙',18)varp2=newPerson('袁一峰',20)上面我们说过,通过new关键字实例化的对象会有一个constructor属性指向其构造函数console.log(p1.constructor===Person)//trueconsole.log(p2.constructor===Person)//true优点:实例化对象和构造函数有关联缺点:浪费内存,在构造函数中定义方法名action是相同,但实例化的对象名称不同,造成内存浪费。原型模式我们上面说过,每个对象在被实例化的时候,都会有一个原型属性,这个属性可以被其他对象继承。所以我们可以把对象共享的属性方法放在原型上,这样每次通过new出来的对象,构造函数中的方法都会被创建多次。functionPerson(name,age){//通过this添加属性方法this.name=namethis.age=age}//把普通方法挂在原型上Person.prototype.action=function(){alert('hellowodr')}//实例化对象varp1=newPerson('尤雨熙',18)varp2=newPerson('袁一峰',20)p1.action()p2.action()property和方法的类型通过原型模式,我们可以将方法属性直接放在原型上,所有实例对象都可以访问这个属性方法,我们称之为公共方法/属性。熟悉ES6的朋友都知道,在使用class定义类的时候,我们可以在里面定义属性方法的类型。不管是保护类型、公有类型还是私有类型,不同类型之间是不能互相访问的。在ES6中,我们可以使用public等关键字来定义,那么在ES5中我们如何区分它们的一种类型呢?以前学面向对象的时候没怎么关注这块内容,现在我们也很少关注这块内容了。其实在高速发展时期,我们很少注意到javascrip的这些基础理论知识,甚至缺乏对nativejs的了解。在面向对象中,每个属性都有自己的类型,可以分为公共的、私有的和静态的。共享属性和方法从字面上理解,共享,就是所有对象都具有的属性或方法。functionPerson(name,age){//通过这个方法添加属性this.name=name//公共属性this.age=age}//挂在原型上的公共方法Person.prototype.action=function(){//publicmethodconsole.log(`${this.name}isfor${this.job}`)}//实例化对象varp1=newPerson('游鱼溪','程序员')p1.action()从上面的代码可以看出,通过this添加的属性或者原型上添加的属性和方法都是常见的调用规则:要调用一个public方法,首先要实例化对象的私有属性和方法private属性的理解可以从函数作用域开始,函数内部定义的变量不能在函数外部访问。我们看下面的栗子functionPerson(name,job){//通过这个添加属性方法varname=name//私有属性varjob=jobfunctionaction(){//私有方法console.log(`${name}就是`)for${job}}}//实例化对象varp=newPerson('游玉玺','programmer')console.log(p.name)//undefinedp.action()//p.actionisnotafunctionerror实例化创建对象时,var定义的局部变量无法被外界访问。只能在构造函数内部使用,不能通过this访问。让我们再次更改代码外观。functionPerson(name,job){//通过这个添加属性方法varname=name//私有属性varjob=jobfunctionaction1(){//私有方法console.log(`${name}is${job}`,'由此调用')}functionaction2(){//私有方法console.log(`${name}由${job}`,'内部调用')}//这是This.action1()不能调用this.nameaction()}//实例化对象varp=newPerson('有雨熙','Programmer')//有雨熙是程序员内部调用调用规则:私有方法和属性对象不能从外部访问,只能在内部使用特权方法。通过this在函数内部创建的属性和方法,在创建对象时,每个对象都会有自己的副本,可以被外部访问。通过this创建的属性可以看作是对象的公共属性,通过this创建的方法不仅可以访问这些对象的公共属性方法,还可以访问自己的私有属性方法,称为特权方法functionPerson(name,job){//通过这个var添加属性方法name=name//私有属性this.job=job//公共属性this.action=function(){//特权方法console.log(`${name}isdry${this.job}'s`)}}//实例化对象varp=newPerson('Youyuxi','programmer')console.log(p.name)p.action()//YouyuXiis干程序员的调用规则:通过实例化,可以访问公有属性方法和私有属性方法静态属性和方法公有属性方法和私有属性方法只能通过new创建对象访问,而静态属性方法不需要通过new访问关键字创建后,可以acc直接ess了functionPerson(name,job){varname=name//私有属性this.job=job//公共属性this.action=function(){//特权方法console.log(`${name}is${this.job}`)}}Person.attr='静态属性'Person.say=function(){console.log('大家好,我是静态方法')}console.log(Person.attr)//StaticpropertyPerson.say()//大家好,我是静态方法//实例化对象varp=newPerson('游鱼溪','Programmer')console.log(p.attr)//undefinedp.say()//错误调用规则:可以在不实例化对象的情况下调用静态方法。对象实例不能调用对象的静态方法,只能调用实例本身的静态属性和方法。静态类前面我们说过,对象的创建有几种形式,那么我们通过字面量形式创建的对象是什么类型的呢?以对象字面量形式创建的对象所添加的方法只能是静态属性和静态方法,包含静态属性和静态方法的类称为静态类varperson={name:"尤雨熙",age:"18",action:function(){console.log('你好!');}}person.attr='我是静态属性'person.say=function(){console.log('大家好,我是静态方法')}console.log(person.name)person.action()person.attrperson.say()调用规则:不需要通过new创建对象//juejin.im/post/684490...)js面向过程编程和面向对象编程的区别JS面向对象编程封装Javascript面向对象(公共方法、私有方法、特权方法、静态属性和方法、静态类)实例讲解