一家之言:说说 JavaScript 的类成员的访问控制

看书的时候遇到这样一个问题,程序代码如下

 

当时很不明白fn1里面第二个alert的结果,为什么this会指向window?

我在群里讨论这个问题,引发一场关于js私有函数的讨论,今天我就说说js的类成员访问控制,郑重声明这只是我的个人观点,仅供讨论。

所谓js的类成员访问机制就是常说的公共成员、私有成员、保护成员。

1 公共成员public member

js实现公共方法是通过prototype属性,prototype是每个对象都具有的一个特别的成员,它定义了对象的内部结构,很类似其他面向对象语言(比如C++)的传统的类(Class),如果你对面向对象不了解,就把它理解为一个对象的蓝图,一旦它被修改,那么所有这个对象的实例和继承这个对象的实例都会发生改变(有点拗口)。

举个例子

 

但是我们不能直接用myConstructor.clearMessage(),因为myConstructor本身是Function对象的实例,而Function本身是没有clearMessage()这个方法的。

关于prototype我想多说一点,关于prototype链,因为每个对象都有一个prototype属性,而prototype本身也是一个对象,所以它也可以包含自己prototype,这样就形成了一个链条,直到链条的最末端就是prototype为null

举个例子

 

我相信会有人疑问第二行的结果,原因就是prototype链,当试图访问一个对象的属性时,js会返回第一个找到的结果,它会从当前对象开始寻找,然后prototype,然后prototype的prototype,直到prototype为null。这个例子中,访问testNumber属性,先找MyObject2,,发现没有,然后找它的prototype(就是MyObject1),找到了值为8.,寻找结束。

第三行的结果呢?MyObject1也没有toString属性呀,怎么办,继续找,MyObject1的prototype就是Object,而Object的prototype就包含toString属性,我们常用toString其实就是原始对象Object的公共方法,明白了吧。

第四行的结果明白了吧,找到原始对象Object的prototype也没,继续找,可惜原始对象的prototype的prototype为null寻找结束,只能返回defined。

2 私有成员private member

确实,js本身是没有传统意义的私有成员的,但是可以通过闭包(闭包是一个很难理解的概念,以后我们会慢慢讨论,这里只讨论私有成员的实现方式)来实现。

实现其实大家都用过,只是不知道而已,就是简单的在函数内部定义变量或者函数。

举个例子

 

第一个错误没问题,第二个可能有不理解的了,私有成员被严格限制在构造函数MyConstructor中,其他所有的地方,包括对象的实例都无法访问。

聪明的同学或许看出来了,这个就是我在学习时遇到的难题,我们要想在私有函数内部正确引用MyConstructor实例的对象,就必须在私有函数外面保存this。this引用当前函数执行时,包含这个函数的对象(我翻译的不好,权威解释 the this keyword within the function would resolve to the object of which the containing function is a method when called)。实例化myConstructor后,myConstructor里this当然就指向myConstructor实例的对象,但是对于私有函数里面的this却不是,所以我们要想在私有函数内部正确使用this就要提前赋值。问题是为什么呢?如果你像我一样进行测试,会发现私有函数alertMessage()里this会指向window,这也是我迷惑的地方,书里的解释如下

Private methods are self-contained objects that exist within the scope of the constructor. They’re not real methods on the prototype, so this within the private method will refer to the private method instance, not the myConstructor instancePrivate

我开始不明白,就发邮件给原书的作者Aaron,他很热情的回答了我的问题,给出的解释是

Ok, so when you create a closure, a lot is determined by the execution context. In the case of the keyword "this," the global object is assigned to it toward the end of the process (per the internals of the ECMAScript spec) if "this" is unassigned (or null).

其实我还是不完全明白,汗!但是我倒是有一些理解,大家不妨做个参考:函数是自包含的对象,它创建的时候默认是赋给window全局对象的,当把这个函数赋给另外一个对象的时候,this的指向就会发生改变,我们知道私有函数是严格限制在构造方法myConstructor里面的,对私有函数来说myConstructor只是一个函数,不是对象(他还没被实例化呢),所以它里面的this当然还是指向window。这样的理解对吗?你说。

那有没有一种既可以访问私有成员,又可以在外面被调用的类型呢?那就是保护成员

3 保护成员privileged member

有的翻译为特权方法,怎么翻译都无所谓,关键要记住它的英文名字。

所谓保护成员就是在名字前面加上this前缀。

举个例子

 

我们发现保护成员可以再外面访问,同时它又可以访问私有成员,为什么,因为他们位于一个同样的作用域(又是一个难懂的概念,汗)。

说到这里吧,写了这个多废话,等待高手检验!关于闭包、作用域这个东西我现在也不能完全理解,有需要的话以后可以拿出来讨论,再次声明,本文章只代表个人观点,无法保证正确性,请读者自己斟酌。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
有这样一类成功者:他们经商致富,于居室外置庭院,院中有亭翼然,亭上挂一面额。此时倘有人将“醉翁亭”题至编额中。主人公拍手称快道:“妙哉!”而若将“饮酒亭”题至匾额中,主人则不假思索道:“俗哉!”此类人追求文人本题。但实际上胸无点墨,只管把自己强行嵌入“雅”的框架中,就如同大观园中只顾赏花却不懂花的“伪君子”,总不免贻笑大方。 自古以来,世上总有各种困在框架里而不自知的人。他们如流水般虚浮,惯于遵从过去的经验或偏听一家,拘泥于既定枢架范式中。这些框架如同牢笼,让人的思维日渐固化,仿佛被“囚”于牢笼中,不见天日。归根结底,还是人本身缺乏硬实力所致。 在崇尚理学的明清时期,几乎所有人都成了封建社会值硬刻板的“木偶人”。可曹雪芹却通过笔下两个鲜明的角色,跳出了框架的束缚。此二人便是贾宝玉和林黛玉。他们不仅才华横溢,也在教育的熏陶中造就了自己独特的思维方式。这是一种因时因地制宜而去伪存真、去粗取精的思维方法,这样的方法可以教会一个人不要只顾跟随领跑者,而要学会超越领跑者,我愿称之为“宝黛思维”。 春秋时期的美女西施,天生丽质,举手投足间都流露着妩媚与柔情,而那些仰慕西施不顾现实加以效仿的人,不仅失去自己的特点,还闹出东施效颦的笑话。在全民创造短视频的热潮中,李子柒结合自己的兴趣与特长,对中国传统文化加以创新,以最具时代特征的形式,推动中国文化走向世界。由此可见,我们为人处世应当学习“宝黛思维”,以因地制宜为前提,实破框架束缚,勇于创新,方能成事。 虽说“他山之石,可以攻玉”。但真正的好玉,还得用心细“攻”,而非“一锤定音”,强行为之套上框架。只有培养并运用“宝黛思维”,才不会在山清水秀时自我陶醉而落入俗套,才不会在山穷水尽时野驴技穷而止步不前。只有跳出框架的人,才能知所进,知所惧,知所适。识时务。 “宝黛思维”可激发人的潜力,帮助我们脱去少年的程格。少年的我们唯有善用“宝黛思维”,方可跳出“囚人”的框架,释放知识和人生的光彩。 总结大意
02-17

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值