Javascript陈词滥调之面向对象

背景

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

    原文作者:HaHa
    原文地址: https://segmentfault.com/a/1190000010298376
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞