elpmis-wu 看到这个名字,你是否觉得挺难读,也不知道是什么涵义,那么请你从右往左看:悟-简单,对了,意思就是:悟通了就觉得简单.在编程的世界里,有很多新概念,如果不清楚这些基本概念就住往觉得这编程语言怎么就那么的难,若当你悟通了,也会觉得挺简单.那么我们首先来悟一下程序员常说的一些术语吧:
1.对象--一切东东都是对象.通俗的说就是:什么都是对象,你所能看到的,听到的,想到的都是对象,抽象概念也是对象.(公司是一个对象,公司的员工又是对象,有个员工叫张三,张三也是个对象,张三天马行空的想法还是对象)所以,对象包括抽象的和具体的,下面所写的的概念都是对象,包括这些文字也是对象,一个字就是一个具体的对象(实例),文字是个抽象的对象(类).2.类---抽象的对象:比如:公司是个类,员工也是个类.抽象类也可有属性.
3.实例--具体的对象:华为是公司类的一个具体实例对象,有个员工叫张三,张三就是员工类对象(抽象对象)的一个具体实例(具体对象)很多书上把实例说成对象,这绝对没错,因为一切都是对象,但这样容易造成误解,认为实例是对象,就会误认为对象就是实例.相当于白马是马,马就是白马.这个就是误解对象的由来.很多人都会有这样的逻辑误区!所以我们叫实例更明确点.就相当我们指着张三对人介绍说:这个人是个对象,但如果说:这个人是张三.这样岂不更好.4.属性--对象所具有的对象:公司(类)具有公司名称(公司类的属性).华为公司(公司类的一个实例)的公司名(华为公司这个实例的属性)叫做华为(华为公司[实例对象]的公司名称[属性对象]的值[这个也是个对象]).所以:华为公司的名称叫华为这句话包括了三个对象.如果属性是抽象类对象的就叫类属性,如果属性是实例对象的就是实例属性.实例属性可以在创建其实例的类对象的内部代码中通过this指定进行定义.5.数据类型--数据对象的类型,在javascript中有6种数据对象的类型: number string boolean undefined object function也就是说我们说的对象(除了意义对象),它们类型只有这6种,其中number string boolean,undefined 是无属性对象的类型(值类型)object function 是有属性对象的类型(引用类型),我们判断一个对象的类型时,用 typeof 对象; 注意 (typeof null) == object;6.实例类型--关系对象:用来描述实例对象与类对象的关系,实例对象的实例类型是其对应的类对象,(华为公司这个实例对象的类型是公司这个类对象,而不是员工类的一个实例对象)比如说: var obj = new Object();Object是个类对象,obj是个实例对象,obj的类型是Object. obj instanceof Object 为true;实例类型的判断其实跟原型链有关, var a.__proto__ = B.prototype; b.prototype.constructor = B;那么a的实例类型就是B请注意区别 数据类型 和 实例类型 的概念,对象都有数据类型,不一定有实例类型,只有实例对象才有实例类型,. 运行一下:var a = new Object();console.log(typeof a, typeof Object, a instanceof Object, Object instanceof Function,Object instanceof Object );
结果为:object function true true true.请注意:object,Object()和我们说的对象意义的不同,弄不清这三者的区别,就直接造成概念性的误解.特别是很多书都把object,Object()翻译成对象,其实,它们的涵义是不一样的.object指的是数据类型,如果一个对象是实例对象,那么它的数据类型是object. 而Object()指的是有一个函数对象,它的标识符是Object,那么Object这个对象的数据类型是function.而我们说的对象,记得吧,一切都是对象同理要区别function 与 Function();function 是指数据类型,函数对象的类型就是function,也就是说Function()的数据类型是function但Function()指的是有个函数对象,其标识符为Function,有意思的是:Function()是所有函数对象的实例类型,包括它本身.
7.函数--计划方案(任务).分为两个过程(声明与运行):声明一个函数就是制定计划方案,运行一个函数就是执行这个计划方案.当然一个计划方案中可能又有多个计划方案组成,或者是定义好实行方案的步骤,或者说在声明这个计划方案时,已经声明需要其它计划方案的运行支持.从大角度来说,程序本身就是一个大函数对象,我们编写的代码就是在制定计划方案,执行这个计划方案的就是运行系统.所以函数要运行才能产生实际效果.所以说我们程序就是在编一个大的函数对象.
函数具有两个功能,一个是声明功能,在声明时就创建了一个函数对象,一个是运行功能,在函数体内进行逻辑操作,对于函数的运行机制,请看下面的内容(特别重要).函数在声明时: 创建了一个函数对象(作为当前所在的函数对象的OA对象的属性),并且为这个函数对象添加了一些隐含的属性对象,
1,__proto__,指向它的原型,默认指向Function.prototype,而Function.prototype.__proto__ 指向 Object.prototype;2.prototype.这是作为它创建出来的实例对象的原型来存在的,其中protoype.constructor再指定,就可以用来判定实例对象
的实例类型了.3.length:形参的个数,
4.scope对象(无法访问),可以认为是栈结构(后进先出),
把函数声明时所在函数对象的VO对象引用入栈顶还有其它的一些隐含对象,我没有研究.
函数在运行时:
1,动态指定this,可以通过a.fb(),call,apply,bind等方式指定,如果是new的话,则this指向{},但如果没有指定this,则this.的指向global对象
(注意this不能通过this = a这样的方式赋值)2.创建实参对象arguments,此对象类似数组,存储实参值.
3,创建AO对象(活动对象),且其所以的函数对象的scope指这OA对象的引用放入栈顶,如果有形参,按内部变量处理,并且引用arguments
按顺序赋值.函数内var声明的对象(初始值为undefined)或者function 声明的对象(此时担声明的函数对象也创建出来,于标识符指向那对象); 所以var a = function(){};和 function a(){}在这时的处理是不同的,var方式 a 的初始值为undefined,等运行到这句时才创建函数对象,并且a指向刚创建的函数对象,而function a(){}方式是还没有运行到这句,已经创建函数对象,并且 a 指向这函数对象.4.开始按顺序执行,若有取值,则在当前的函数的scope中查找(作用域查找机制,对象的属性值按原型链查找),直找到global对象(scope最底的OA对象),再查找到globa的原型Object.prototype如果没有找到则取值为undefined. 如果执行到return ,若不指明return 值,则返回this指向的对象.
所以new操作就是刚开始把this指向{},默认返回this指向的对象,有return 对象,则返回指定对象.得到的实例对像的__proto__值指向函数对象的prototype对象,用函数对象的prototype的constructor来指实例对象的实例类型.函数返回时:清理战场工作,如果返回对象中没有引用到的对象,则交由GC处理,如果返回对象有对此对象的引用,这样的对象则不能被清理,所以这样就形成了闭包以及封闭,合理安排引用关系,是处理闭包带来的问题的关键.
8.方法--主要是用来做逻辑控制.在java中,属性分为字段和方法,其中方法==函数,方法(函数)不是对象,或者也可以说是对象,只是这个对象不能拥有方法(函数)不能够添加属性.但在javascript中,方法就是函数对象,通常指的对象的属性是一个函数对象,我们就称这个函数对象是实例对象的一个方法在JAVA中,函数不是对象,但在javascript中,函数是对象,函数对象有类对象的所有功能,可以用来创建实例对象从这个角度来看,javascript比JAVA更面向对象.(因为Java中有不是对象的东东存在,javascript中所有东东都是对象这才是我们这里说的面向对象,并且在javascript中,函数允许传递函数对象,返回函数对象,从而产生闭包以及功能强大的回调功能和this的动态指定)
9.编译--就是把你写的计划方案(程序代码是些字符串)翻译成运行系统能识别的方式.相当你用中文写好了 计划方案,将交给外国人去执行,那么需要将中文翻译成英文先吧10.执行环境--相当于执行计划方案的执行小组.在avascript中,函数对象有执行上下文.11.设计模式--对象的声明,创建,调配,运行,消亡等这一系列的常见方法的总结(注意时空概念下面有专门论述).掌握到这些人们所总结出来的方法,有利于提高我们写函数(编程)的效率 并且能很好的处理对象关系.就比如如果叫你写一份创业方案,如果你都不知道怎么去融资,怎么去利用,怎么去整合资源,怎么是运营 那是不是很难呀,但如果有人总结出融资的模式,整合资源的方式,运营等,我们就可以根据实际情况参考这些处理方式去创业了....12.框架--公司模版:依靠这个模式可以快速的创建出自己的公司,有点像类对象创建实例对象一样... 也可以用函数这个角度来理解,一个框架就相当一个大的函数对象,在这大的计划方案模板中添加自己的计划方案13.数据库--仓库,公司有实际产品的话,总需要地方来存吧.从对象角度来看,如果想保存对象的状态以供其它的对象跨时空的去利用,是不是得把这 些对象的状态保存下来.注意:时空!!14.前端--相当于市场营销,侧重于怎么去与客户交互,把客户的需求反映给公司,把公司提供的服务提供给客户15.后端--公司内部的管理运营,同时对计划方案提供服务支持16.时空--其实这个词并不是程序员常说的术语,而是程序员最不常说的,但我认为非常非常的重要,国为这是一切对象存在的最重要的特性,所以不得不来说明.首先来看这句:飞流直下三千尺,疑是银河落九天.不得不佩服李白超乎想像的空间感,和时间感(飞流直下),我觉得这句诗好,是因为它既展现了对象的巨大空间,也留给人巨大的想象空间(这是我自己的个评), 我给它再加上长的时间: 飞流直下三千尺,疑是银河落九天.随波逐流何时止?源远流长几万年! 虽然显得有点不伦不类,但我想说明的是对象存在时空性.我们欣赏一个对象的生命力,常常取决于它的时空性.同样,我们衡量程序的标准是什么?我觉得的关键在于它在满足功能且稳定运行的同时还得小,巧,精.也就是说占用硬盘内存等空间小,操作灵活,容易被扩展(时间性).像我们用的IDE,比如,Eclipe,webStorm哪个不是小巧精,尤其是Sublime,在这方面做得尤其出色. 当然这些是从宏观角度上来看的,量变引起质变,那我从微观来分析一下:对象的生命周期,作用域,闭包,原型链,函数的声明与运行,回调,this的动态绑定,事件驱动等等,有哪些不是从时空性出发.....,程序设计就在设计对象存在的时空性,根据时空性,对象分为两大类:1.标识对象(大多时是变量,也可能是对象的属性)
2.数据对象.
为了说明这个问题,我先作个比喻,张三租了房子,房子很小(10几平米),但却有个非常大的地下窒(200平米)张三的家私不少,反正该有的都有,不应该有的也有.那么房子里放些必用品,其它乱七八糟的东东全放地下窒,等有需要需要再取来,张三还特别喜欢购物,三天两头的就买东东回来.张三有一条狗,特聪明,正所谓人有超人,狗也有超狗,超狗有个非凡能力,叫隔空控物,张三的东西交由超狗去处理,由超狗去放,去取.张三需要控制东东时,就写在纸条上:C--冰箱,超狗根据冰箱的地址,用C来引用到冰箱.好了,现在我们来进行类比(虚构),小房间(程序内存),地下窒(数据内存),张三(控制中心),超狗(服务中心),纸条(标识关系)电冰箱(数据对象),当张三买回来(创建对象时)笔时,发现是个小物件(值类型,比如number,string,boolean型),就只放在小房间内(程序内存),并且张三进行标识: A--笔,B--纸之类的,当张三买回来(创建)冰箱时(值类型,比如object,function),大都情况下张三这时会标识:C--冰箱,超狗就会把冰箱放到地下窒(数据内存)所以在地下窒(数据内存中)就产生了这样的一个数据对象:(100,300)--冰箱,同时为了张三标识的C--冰箱,而创建一个标识对象C--(100,300),以上就是数据对象和标识对象的创建过程,当张三需要冰箱时,就是用到C,这时超狗就会根据标识对象C--(100,300) 和数据对象:(100,300)--冰箱这两个的相同地址,就能关联起形成:C--冰箱.从而C就代表着冰箱.这就是取值过程. 当张三第二天又用到冰箱时,忘了原来的标识字母,就从新写着D--冰箱,但因为冰箱不在小房间内(程序内存)要去地下室取,从而产生出D--(100,300)这样的标识对象,同理根据标识对象D--(100,300) 和数据对象:(100,300)--冰箱关联成D--冰箱张三控制标识符D就相当于控制了地下窒中的冰箱.一般情况下,当张三控制完成后,标识对象要被清理(作用域机制),但数据对象仍会存在数据内存中,如果确定没有任何的标识对象指向这数据对象,那么数据对象就会被清理.(GC机制)这就是消亡过理.所以标识对象存在于程序内存,而数据对象存在于数据内存中,两个对象的存在空间是不一样的,通过寻址机制而能跨空间进行控制,因为存在空间不一样,所以也会造成对象的生命周期不一样,var标识对象依附于函数内的OA对象,当OA对象(没有被引用)被清理掉,那么依附在其的标识对象也会被清理,但此函数过程中创建出来的数据对象还不一定被清理,如果没有没有被引用,则会被清理,如果被返回或者被引用,则不会清理所以这两种对象的生命周期是不一样的.比如: function Fa(){var a = {name: 3};return a;}; Fa();当返return a时,返回的并不是a这个标识对象,而是{name: 3},函数结束返回,OA对象被清理,标识对象a也被清理,但{name: 3}数据对象却不会被清理,虽然它是在函数内创建的.注意,标识对象只能作用于函数内,当函数内再声明有函数,并且返回结果中有内声明的函数,那么此函数的OA对象不能被清理,那么标识对象也会不能被清理,这样就形成了闭包.如: function Fa(){var a = {name: 3}; return function(){console.log(a.name)}}; var b = Fa(); b();在Fa();结束后, 因为返回结果的函数中有对Fa函数的OA对象进行引用(作用域链机制),所以OA不能被清理,那么a也不能被清理,所以b();中还是可以用到标识对象a;通过数据对象,就可以形成了跨时空性的访问和操作.如果数据对象被持久性,也就是存储到硬盘中,就形成了数据库,有了数据库,数据对象更显出跨时空性,因为不同的应用程序或者是不同的时间都可以从数据库中取出数据对象,所以数据库的主要作用就是使数据对象有了更大的跨时空性. 注意:数据对象中也可以有标识对象的存在,以属性方式存在,那么此标识对象依附于此数据对象.因为对象的时空性也会带来某些问题,为了更好的处理对象间的关系,大神们总结出了设计模式,这有待我去研究 现在我们先来看看一个简单的例子吧*///首先从细角度来进行对象分析: 上面代码中有哪些的对象呢?(除了意义对象,内置对象和console.log())之外,请看注释function Fa(){ //函数对象声明时,其实可以认为这有两个对象,一个是数据对象function (){} ,一个是标识对象Fa相当var Fa ,Fa对象引用(指向)function (){}这个数据对象 //function (){}的数据类型为function,实例类型为Function,因为Fa对象引用它,所以Fa对象的数据类型也为function,实例类型为Function
//这里有4个对象,分别是a,{name: "a"},name,"a",其中a和name是标识
// 对象,而"a"和{name: "a"}是数据对象,因为"a"是值类型,不用存储到数据内存中,直接存到标识对象中, //a指向{name: "a"},此时a的数据类型是object,实例类型是Object,而name的数据类型是string,没有实例类型. var a = {name: "a"}; //同上分析 var b = {name: "b"}; //赋值关系,因为b是标识对象,所以a 也指向b的指向{name: "b"},这时 {name: "a"}没有指向,那么应该被GC清理掉了. a = b; //函数返回时,因为返回结果没有对函数内这些对象进行引用,所以上面函数内的标识对象a,b全被处理掉.但return a指的是返回a的数据对象,那么 //{name: "b"}这个数据对象不会被清理. return a;}//函数对象运行时, 在函数体内的对象是在运行时才能创建和控制
var data = Fa();//此时的data标识对象指向所返回的数据对象 {name: "b"}