史上最全js原型/原型链,面向对象编程讲解

前言

本少观过诸多视频和文章,奈何使用频率少之又少,每次一到用处,发现忘的一干二净.然后又重头温习,记得笔记也丢三落四,找不到;所以存到网上,方便以后查询.这里吐槽一句,很多文章以偏概全,不得要领,实在让我头皮发麻.还是自己写一篇全文记载,美滋滋.

场景模拟

俗话说,好的解决方法,都是由于碰到了问题.没有问题的理论讲解,都是赤裸裸的耍流氓.讲解问题没有场景模拟,都是凑不要脸.那么看下,是哪些问题让我痛定思痛,写这篇文章:

场景1:我与我漂亮的女同事,一起写一个项目,等她上传完svn后,我更新到我自己的电脑
上跑,因为她加了一些js和java类,导致我项目跑不起来,然后我干脆一不做二不休,把她加
的都删除掉,结果删啊删,删啊删,我发现项目快被我删完了.这就是典型的面向过程写程序
一环套一环.从那时起,我就清楚的认识到了面向对象编程的好处.

场景2:我的项目大概有几十万行代码.项目上线后,中途boss让我加一个模块;我想么,加个
模块很easy的啦.然后我就写了个js,往main.html里面一丢.就报各种错误.项目大了,很不
好查的.然后在我排查了一天的情况下,发现是变量污染了,也就是变量重复了.我的天啊,
一天就没了,从此我意识到了防止变量污染的重要性.

场景复现

在这里插入图片描述
我这里复现下变量污染的情况,这是我的目录,你可以假设js很多,有几十万个.
在这里插入图片描述
在这里插入图片描述
上面是我文件的代码.显然,我是希望输出5,3;也就是说,在test.html中,money是5,在js1.js中
money是3;但是你会发现,我输出的都是3.所以也就是说,money被污染了.
在这里插入图片描述

让我们来谈谈函数(万物皆对象)

函数:Funtion类型,其实函数也是对象,仔细想想这句话;

我们声明对象的方式:

方式一: var superman={};
方式二: var superman=new Superman();

我们声明函数的方式:

函数声明: function superman(x,y){};
函数表达式: var superman = function(x,y){};
Function构造函数: var superman = new Function("x","y","dosomething");//不推荐

我们可以看到,函数其实真的是一个对象…函数是对象,函数名是指针(哎,又引入指针了);我们还是不理解了.反正总的来说.我们知道了函数是对象(死记硬背吧);
咳咳咳,貌似没讲清楚,不过我们往下看:
我们稀里糊涂的可以认为:“我认识一个超人,他叫tom,今年25岁,喜欢把裤衩穿在外面”,那么
我们一般可以这么定义它:

var superman={
"name":"tom",
"age":25,
out_kucha:function(){console.log("out kucha")}
}
说明:out_kucha是方法,不能写成out_kucha=function(){}的形式,因为在对象里,存储的是键值对的形式.

我们的大脑会很自然的想到这种定义方式,那么问题又来了,超人那么厉害,我们自然希望能有更多的超人来保卫地球,我们能想到的除了让超人自然繁衍外,就只生下克隆了.说道克隆,我们肯定不希望让克隆医生一个一个的去克隆.因为那样既麻烦又费力.设想一下,克隆一个超人,要花费1年的时间,那么克隆100个,不就要花费100年的时间了吗?所以,我们希望能有一种即时复制的办法,就跟用光盘给电脑装系统一样.所以,我们希望有一个这样的办法,取个名字,输入个年龄,就能自动的给我们产生一个超人:

function createSuperman(name,age){
var o =new Object();
o.name = name;
o.age=age
o.out_kucha=function(){console.log("out kucha")}
return o;
}

那么我们只需要传入姓名和年龄,就能得到一个超人了.

var superman1=createSuperman("小王","22");
这样我们就得到了超人1,小王;我们可以通过superman1.name去查他的名字.

以前我们批量创建超人,是通过var super1={…},var super2={…},…;
现在我们批量创建超人,直接通过上面的方法就可以了,这样,对于创建的属性,我们就可以提出来,节省了不少代码.

诶,你想到了这些,那其他人肯定也能想到.所以就有个大牛,叫什么呢.我去查了下,没查到…他就牛逼了.他感觉啊.这样是不错.但是应该还可以改进.他就发明了构造函数.他认为.所有的函数,创建object对象,赋值,和返回都是共通的.那他就封装下(这个封装很麻烦);然后让操作这直接传参就可以了;

function CreateSuperman(name,age){
//var o =new Object();
//o.name = name;
//o.age=age
this.name=name;//this 指向调用者
this.age=age;
o.out_kucha=function(){console.log("out kucha")}
//return o;
}
使用方法:var super1=new CreateSuperman("小明","21");
new 字符帮我们做了我注释的三步.就是声明Object,赋值,和返回本体.
构造函数约定俗称的,首字母大写.人为规定的.

诶,我们发现,通过构造函数批量创建对象,是一件很愉快的事.然后呢,我就打开了我的vscode,试验了一下:
在这里插入图片描述
诶,我发现构造函数当普通函数使用的话,就是没有new,变量赋给了window.想想也是可以理解的.因为没有new,相当于没有绑定到对象;this向上级找,自然就是到window了.
然后我们通过new再来看看:
在这里插入图片描述
是不是很神奇,我记得以前看视频讲的时候,new其实是做了很多事情的,远比我们想象的多.
这一切看似很美好.可是随着人类文明的进步,很多人啊,年龄各不相同,但是呢,都做着同样的事.比如啊,我们程序员,年龄,性别,家庭都不同,但是呢,我们只需要做一件事,就是敲代码;那这样的话,我们通过构造函数来声明,就会发现,我们的dosth都是同样的事.那么在函数里,我们就会占用很多内存?(反正要占用很多东西,是内存还是栈堆忘记了,毕竟我不懂指针);哦,老天,反正你知道,这样很不好就对了,比如像下面这样:
在这里插入图片描述
emmmm,有些牛逼的人,就开始作妖了.我要是能把它搞出来就好了;于是…
在这里插入图片描述
有人就把方法提出来了;但是他发现,如果要做的事情很多呢?那么我就要在全局中定义很多个普通函数;没事,多就多,我可以手写一个月!!!我可以接受,我认为可以.但是,突然有一天,我发现我定义的函数,别人也可以引用.我靠,这我就不能忍了.我好容易new的苍老师,别人也能用,那是万万不行的.因为在全局定义函数,是个人都能引用啊.所以我要想个办法解决它.诶,这个时候又有牛逼的人站了出来,弄了原型.

原型

诶,我们来看看,我们刚new出来的小明
在这里插入图片描述
他有age,name,dosth,_proto_四个属性.前三个,我们很熟悉,毕竟我们自己创建的嘛.
emmmmm.我们来看下原型的定义:
创建的每个函数,都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的包含由特定类型的所有实例共享的属性和方法.(其实我压根没懂).虽然我没懂,但是我会敲代码啊:
在这里插入图片描述
这不敲不知道,一敲吓一跳.原来通过prototype写的内容,都跑到_proto_里面去了啊.那我们岂不是能把公共的属性方法通过这样去搞?答案是肯定的.
对不起,在这里我们不会记录什么Prototype指向谁,然后什么原型指向什么对象,对,没错,就是那个图!!因为我根本记不住.我只想拿起来就用.我不会去说什么instansof去检测啊,has…去检测啊,cconstructor指向谁啊.因为我根本记不住.好了.我现在知道了原型是有什么用处了.但是,很显然,原型致命的弱点,就是它的属性和方法都是共享的,那么我们要解决它.

确定风格

我们通过上述的分析.基本已经了解了构造函数和原型的作用.为了更好的编程,我们要有自己的风格,也就是规范.

构造函数和原型共用风格

在这里插入图片描述
这样写,我们能够确保共用的和独特的属性都满足.这种风格用的最多,最广泛,所以我也像这样用了.至于上面说的什么工厂模式啊,寄生模式啊,了解下就行了.

终极问题

既然我们确立了编程风格,但有一个问题一直困扰我很久,我经常看到jquery源代码里,各种立即执行函数封装,各种原型…终于;我明白了.立即执行可以让prototype变的私有啊.简单的说,如果我有一个main.html,one.js;我在HTML中引入one.js;我在one.js中如果只用构造函数和原型来声明的话,那么我的原型是会被污染的,而立即执行函数解决了这个问题;哈哈哈哈哈,这就是传说中的封装和模块开发啊.哎,又要去研究模块开发了.

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李卓书

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值