目录
getter和setter如何工作?
问题在哪里?
seal行不行
类的到来
proxy来帮助?
首页 web前端 js教程 JavaScript中使用getter与setter为什么不好呢

JavaScript中使用getter与setter为什么不好呢

Jul 18, 2017 pm 04:08 PM
getter javascript setter

如你所知,getter和setter已经成为了JavaScript的一部分。它们广泛支持所有的主流浏览器,甚至是IE8。

我不认为这个点子通常是错误的,但我认为它不是非常适合JavaScript。可能看起来getter和setter可以简化代码和节省时间,但其实它们会带来隐藏错误,并且这些错误第一眼看并不明显。

getter和setter如何工作?

首先小小地总结一下这些是什么东西:

有时候,我们希望能允许访问一个会返回动态计算值的属性,或者你可能想要反映内部变量的状态,而不使用显式的方法调用。

为了说明它们是如何工作的,让我们来看一个有着两个属性的person对象,这两个属性为:firstName和lastName,以及一个计算值:fullName。

var obj = {
  firstName: "Maks",
  lastName: "Nemisj"
}
登录后复制

计算值fullName会返回firstName和lastName两者的串联。

Object.defineProperty(person, 'fullName', {
  get: function () {
    return this.firstName + ' ' + this.lastName;
  }
});
登录后复制

为了得到fullName的计算值,不需要像person.fullName()带可怕的括号,只需要使用简单的var fullName = person.fullName。

这同样适用于setter,你可以通过使用函数设置值:

Object.defineProperty(person, 'fullName', {
  set: function (value) {
    var names = value.split(' ');
    this.firstName = names[0];
    this.lastName = names[1];
  }
});
登录后复制

使用就和getter一样简单:person.fullName = ‘Boris Gorbachev’。这将调用上面定义的函数,并分离Boris Gorbachev成firstName和lastName。

问题在哪里?

你也许在想:“嘿,我喜欢getter和setter方法,它们感觉更自然,就像JSON一样。”你说得对,它们的确是这样的,但是我们先退一步来看一看fullName在getter和setter之前是如何工作的。

为得到值,我们将使用类似于getFullName()的一些东西,以及为了设置值,我们将使用person.setFullName(‘Maks Nemisj’)。

如果拼错函数名,person.getFullName()写成person.getFulName()会发生什么呢?

JavaScript会给出一个错误:

person.getFulName();
       ^
TypeError: undefined is not a function
登录后复制

这个错误会在适当的时候适当的地方被触发。访问函数不存在的对象将触发错误——这是好的。

现在,让我们来看看当用错误的名称来使用setter的时候会发生什么?

person.fulName = 'Boris Gorbachev';
登录后复制

什么也没有。对象是可扩展的,可以动态分配键和值,因此不会有错误在运行时被抛出。

这样的行为意味着错误可能显示在用户界面上的某个地方,或者,当某些操作被执行在错误的值上时,而并非是打字错误的时刻。

跟踪应该发生在过去但却显示在将来的代码流上的错误是如此有意思。

seal行不行

这个问题可以通过sealAPI来部分解决。只要对象是密封的,它就不能突变,也就是意味着fulName将试图分配一个新键到person对象,并且它会失败。

出于某种原因,当我在Node.js V4.0测试这个的时候,它没有按照我期待的那样工作。所以,我不能确保这个解决方案。

而更令人沮丧的是,对于setter一点也没有解决方法。正如我前面提到的,对象是可扩展和可故障保护的,这意味着访问一个不存在的键不会导致任何错误。

如果这种情况只适用于对象的文字的话,我不会多此一举地写这篇文章,但在ECMAScript 2015(ES6)和用类定义getter和setter能力的兴起之后,我决定写下关于潜在陷阱的博客。

类的到来

我知道当前类在一些JavaScript社区不是非常受欢迎。人们对在函数式/基于原型的语言,例如JavaScript中是否需要它们,争执不休。然而,事实是,类就在ECMAScript 2015(ES6)规范说明中,并且将存在于此一段时间。

对我来说,类是指定在类的外部世界(消费者)和应用程序的内部世界之间的定义良好的API的一种方式。这就是白纸黑字放入规则的抽象,并且我们假定这些规则不会很快改变。

改进person对象,做一个它的real类。person定义了接口用于获取和设置fullName。

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  getFullName() {
    return this.firstName + ' ' + this.lastName;
  }
  setFullName(value) {
    var names = value.split(' ');
    this.firstName = names[0];
    this.lastName = names[1];
  }
}
登录后复制

类定义了一个严格的接口描述,但getter和setter方法使其变得不太严格。我们已经习惯了臃肿的错误,当工作于对象文字和JSON时的键中出现拼写错误的时候。我希望至少类能够更严格,并且在这个意义上,提供更好的反馈给开发人员。

虽然这种情况在定义getter和setter在一个类上的时候没有任何不同。但它不会阻止任何人拼错。

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  get fullName() {
    return this.firstName + ' ' + this.lastName;
  }
  set fullName(value) {
    var names = value.split(' ');
    this.firstName = names[0];
    this.lastName = names[1];
  }
}
登录后复制

有拼写错误的执行不会给出任何错误:

var person = new Person('Maks', 'Nemisj');
console.log(person.fulName);
登录后复制

同样不严格,不冗长,不可追踪的行为导致可能会出错。

在我发现这一点后,我有一个问题:在使用getter和setter的时候,有没有什么可以做的,以便于使得类更严格?我发现:有是肯定有,但是这值得吗?增加额外层次的复杂性到代码就只是为了使用数量更少的括号?对于API定义,也可以不使用getter和setter,而这样一来就能解决这个问题。除非你是一个铁杆开发人员,并愿意继续进行,不然还有另一种解决方案,如下所述。

proxy来帮助?

除了getter和setter方法,ECMAScript 2015(ES6)还自带proxy对象。proxy可以帮助你确定委托方法,这些委托方法可以在实际访问键执行之前,用来执行各种操作。事实上,它看起来像动态getter / setter方法。

proxy对象可以用来捕捉任何到类的实例的访问,并且如果在类中没有找到预先定义的getter或setter就会抛出错误。

为了做到这一点,必须执行下面两个操作:

  • 创建基于Person原型的getter和setter清单。

  • 创建将测试这些清单的Proxy对象。

让我们来实现它。

首先,为了找出什么样的getter和setter方法可以用在类Person上,可以使用getOwnPropertyNames和getOwnPropertyDescriptor:

var names = Object.getOwnPropertyNames(Person.prototype);
var getters = names.filter((name) => {
  var result =  Object.getOwnPropertyDescriptor(Person.prototype, name);
  return !!result.get;
});
var setters = names.filter((name) => {
  var result =  Object.getOwnPropertyDescriptor(Person.prototype, name);
  return !!result.set;
});
登录后复制

在此之后,创建一个Proxy对象:

var handler = {
  get(target, name) {
    if (getters.indexOf(name) != -1) {
      return target[name];
    }
    throw new Error('Getter "' + name + '" not found in "Person"');
  },
  set(target, name) {
    if (setters.indexOf(name) != -1) {
      return target[name];
    }
    throw new Error('Setter "' + name + '" not found in "Person"');
  }
};
person = new Proxy(person, handler);
登录后复制

现在,只要你尝试访问person.fulName,就会显示Error: Getter “fulName” not found in “Person”的消息。

以上是JavaScript中使用getter与setter为什么不好呢的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统 如何使用WebSocket和JavaScript实现在线语音识别系统 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术 WebSocket与JavaScript:实现实时监控系统的关键技术 Dec 17, 2023 pm 05:30 PM

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统 如何利用JavaScript和WebSocket实现实时在线点餐系统 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

如何使用WebSocket和JavaScript实现在线预约系统 如何使用WebSocket和JavaScript实现在线预约系统 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

JavaScript和WebSocket:打造高效的实时天气预报系统 JavaScript和WebSocket:打造高效的实时天气预报系统 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

简易JavaScript教程:获取HTTP状态码的方法 简易JavaScript教程:获取HTTP状态码的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

javascript中如何使用insertBefore javascript中如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用于在DOM树中插入一个新的节点。这个方法需要两个参数:要插入的新节点和参考节点(即新节点将要被插入的位置的节点)。

如何在JavaScript中获取HTTP状态码的简单方法 如何在JavaScript中获取HTTP状态码的简单方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP状态码获取方法简介:在进行前端开发中,我们常常需要处理与后端接口的交互,而HTTP状态码就是其中非常重要的一部分。了解和获取HTTP状态码有助于我们更好地处理接口返回的数据。本文将介绍使用JavaScript获取HTTP状态码的方法,并提供具体代码示例。一、什么是HTTP状态码HTTP状态码是指当浏览器向服务器发起请求时,服务

See all articles