资讯专栏INFORMATION COLUMN

Javascript老生常谈之面向对象

TwIStOy / 590人阅读

摘要:内部维护一个叫的局部变量,数组类型,用于存储购买的物品清单。分析看到这题的第一反应就是用构造函数来写。二属性外部只能访问不能修改这个用闭包也能解决,但是这样记不能通过构造函数来实现了,背离了初衷,不行不过我后面还是会给出这种写法。

背景

作为一个前端新人,免不了加各种群,和其他小伙伴们一起学习(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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84226.html

相关文章

  • JS组件开发面向对象及物理模型编程

    摘要:内容简介,关于面向对象,关于面向物理模型,示例,总结,关于面向对象中的面向对象是一个老生常谈的问题,可能有人问你的话你也能霹雳啪啦的说一通,比如最常见的,对象的三要素对象的名字对象的属性对象的方法例子对象名示例对象属性对象方法或者稍微高级一 内容简介: 1,关于面向对象 2,关于面向物理模型 3,示例 4,总结 1,关于面向对象 javascript中的面向对象是一个老生常谈的问...

    cnTomato 评论0 收藏0
  • 深入JavaScript(一)this & Prototype

    摘要:然而事实上并不是。函数本身也是一个对象,但是给这个对象添加属性并不能影响。一图胜千言作者给出的解决方案,没有麻烦的,没有虚伪的,没有混淆视线的,原型链连接不再赤裸裸。所以是这样的一个函数以为构造函数,为原型。 注意:本文章是个人《You Don’t Know JS》的读书笔记。在看backbone源码的时候看到这么一小段,看上去很小,其实忽略了也没有太大理解的问题。但是不知道为什么,我...

    The question 评论0 收藏0
  • 老生常谈javascriptcall,apply的区别

    摘要:开始看到的函数和时,非常的模糊,不知所云,然后看书,网上查询多少知道点了眉目,下面是我做的笔记,希望和大家分享,有不对之处希望各位多多指正,共同进步。。。 开始看到javascript的函数apply和call时,非常的模糊,不知所云,然后看书,网上查询多少知道点了眉目,下面是我做的笔记,希望和大家分享,有不对之处希望各位多多指正,共同进步。。。本文将从三个方面介绍apply,call...

    高胜山 评论0 收藏0
  • 老生常谈javascriptcall,apply的区别

    摘要:刚开始看到的函数和时,非常的模糊,不知所云,然后看书,网上查询多少知道点了眉目,下面是我做的笔记,希望和大家分享,有不对之处希望各位多多指正,共同进步。。。 刚开始看到javascript的函数apply和call时,非常的模糊,不知所云,然后看书,网上查询多少知道点了眉目,下面是我做的笔记,希望和大家分享,有不对之处希望各位多多指正,共同进步。。。本文将从三个方面介绍apply,ca...

    rollback 评论0 收藏0
  • 老生常谈闭包(你不可不知的若干知识点)

    摘要:闭包是什么这是一个在面试的过程中出现的概率为以上的问题,也是我们张口就来的问题。文章推荐我们面试中在被问到闭包这个问题是要注意的几点闭包的延伸,让面试变得 闭包是什么?这是一个在面试的过程中出现的概率为60%以上的问题,也是我们张口就来的问题。但是我们往往发现,在面试的过程中我们的回答并不那么让面试官满意,我们虽然能张口说出一些但是却不能系统的对这个问题进行回答。面试官希望加入自己团队...

    daydream 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<