博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Javascript老生常谈之面向对象
阅读量:5820 次
发布时间:2019-06-18

本文共 2349 字,大约阅读时间需要 7 分钟。

背景

作为一个前端新人,免不了加各种群,和其他小伙伴们一起学习(chui bi),互相帮助(bi can)。前几天一个小伙伴在群里发了道自己去面试的笔试题,我写了一下,一时间没能实现,今天又折腾了一下,虽然大致实现了,但不知道是否优雅,分享自己解法的同时也想请大佬指点一二。

题目

编写一个名字为Person的对象,要求

  • 有一个name属性,外部只能访问不能修改,初始化时赋值。

  • 内部维护一个叫things的局部变量,数组类型,用于存储购买的物品(something)清单。

  • 有一个buy(something)方法,用于购买物品(something)

  • 具有count属性,用于指示一共买了多少物品。

分析

看到这题的第一反应就是用构造函数/class来写。Person对象应该就是一个Person类。

两个属性一个方法,嗯,没什么问题。只有2个点需要考虑:

一、 这个things局部变量是个啥?是属性吗?

  • 应该不是,既然特意指出了,肯定有他的考虑,那么既然是局部变量,外部也是访问不到的,这个应该用闭包写。

二、 name属性外部只能访问不能修改.

  • 这个用闭包也能解决,但是这样记不能通过构造函数/class来实现了,背离了初衷,不行(不过我后面还是会给出这种写法)。那么(以我的水平)就只能用Proxy或者class,这2个都能拦截对象属性的读/写。2种我都试过,采用Proxy,原因下面会讲。

代码

class Person {    constructor(name,count=0) {        this.name = name;        this.count = count;        this.init()    }    //初始化函数    init() {        var things = [];         Person.prototype.buy = (something) => { //为了形成闭包,显式将buy方法写到Person的原型上            things.push(something);            this.count = things.length;        }    }}//Proxy handler对象,定义行为var handler = {    set(target,prop,value,receiver) {//拦截set行为        if(prop == 'name') {            throw Error('不可以哦') //这里自定义你的逻辑,也可以alert等。        }        Reflect.set(target,prop,value,receiver) //不要忘了对其余属性'放行'    }}var p1 = new Proxy(new Person('张三'),handler)console.log(p1.name) //张三p1.name = '李四' //Error:不可以哦p1.buy('猫粮');p1.buy('猫砂');console.log(p1.count) //2//如果需要从'内部'修改p1的名字,则需要先对被代理对象进行定义var _p1 = new Person('张三');var p1 = new Proxy(_p1,handler)console.log(p1.name); //张三_p1.name = '李四';console.log(p1.name) //李四

以上我对这道题的理解。至于为什么不用class的setter,是因为这样写后,在new Person的时候不能传name进去,因为一传进去就会被拦截。所以只能先初始化对name赋值,再进行proxy代理对name拦截。

另一种“野路子”写法

var Person = function(name,count=0) {    var things = [],name = name        result = {            count = count;        };    result.__proto__ = {        buy:function(something) {            things.push(something);            result.count = things.length;        },        getName:function() { // 通过getName函数来获取名字            return name;        }    }    return result;}var p2 = Person('王五'); p2.getName() //王五p2.name = 123;p2.getName() //王五p2.buy('妙鲜包');console.log(p2.count) // 1

两种方法见仁见智,第二种野路子不用Proxy代理,返回的是Object对象,而第一种正规军则返回Person对象,更符合题意。


结语

写到这不知道大家发现了没。 其实第一种方法也可以不需要proxy代理,再init函数中定义name = this.name,再在Person原型上写一个getName函数,这样2种方法的优点就结合到一起了Σ(っ °Д °;)っ

这2小时没有白花,这文章没有白写,又赚到了^ ^。
希望能给大家带来一点点收获,如果有不同的看法可以留言一起探讨()。

Thanks for reading

转载地址:http://yfzdx.baihongyu.com/

你可能感兴趣的文章
C#中的Marshal
查看>>
linux命令:ls
查看>>
Using RequireJS in AngularJS Applications
查看>>
hdu 2444(二分图最大匹配)
查看>>
【SAP HANA】关于SAP HANA中带层次结构的计算视图Cacultation View创建、激活状况下在系统中生成对象的研究...
查看>>
DevOps 前世今生 | mPaaS 线上直播 CodeHub #1 回顾
查看>>
iOS 解决UITabelView刷新闪动
查看>>
Web前端JQuery入门实战案例
查看>>
CentOS 7 装vim遇到的问题和解决方法
查看>>
JavaScript基础教程1-20160612
查看>>
iOS \U7ea2 乱码 转换
查看>>
FCN图像分割
查看>>
ios xmpp demo
查看>>
python matplotlib 中文显示参数设置
查看>>
【ros】Create a ROS package:package dependencies报错
查看>>
HDU1576 A/B【扩展欧几里得算法】
查看>>
WebApi系列~目录
查看>>
通过容器编排和服务网格来改进Java微服务的可测性
查看>>
re:Invent解读:没想到你是这样的AWS
查看>>
PyTips 0x02 - Python 中的函数式编程
查看>>