javascript - Javascript中的密封对象和检查对象的类型
问题描述
这个问题的背景
我最近开始使用 karma 和 Jasmine 在 Javascript 中进行测试驱动开发 (TDD)。我想开发适当的测试以及处理所有可能性的良好代码。这也意味着我要检查测试用例中正确类型的对象。
当前问题
从 AJAX 调用返回的 JSON 数据应与对象匹配,以确保返回正确的数据。为此,我想出了以下代码(简化);
var MyClass = {};
Object.defineProperties(MyClass, {
Key: {
value: '',
writable: true
}
});
var sealed = Object.seal(MyClass);
try {
$.extend(sealed, jsonResponse);
return sealed;
} catch(e) {
return false;
}
这按预期工作,如果任何额外的属性是 JSON 的一部分,false
则将返回。到目前为止,一切都很好。我还想做的是检查返回的数据是否是正确的“类型”。我可以通过使用函数而不是对象来做到这一点:
var MyClass = function() {
this.key= '123';
};
var myClass = new MyClass();
console.log(myClass instanceof MyClass); // True
但是我想不出如何将两者结合起来,所以我既可以确保没有属性被添加到对象中,也可以检查正确的“类”。在第一种情况下typeof sealed
,总是会产生“对象”。
限制
我还需要支持 Internet Explorer 11,所以我不能使用class MyClass { ... }
.
解决方案
如果我对您的理解正确,则组合版本将是:
// The "class"
var MyClass = function(data) {
// Create all the allowed properties
this.key = '123';
// Seal the instance so others can't be created
Object.seal(this);
// If data was supplied, apply it
if (data) {
$.extend(this, data);
}
};
// The instance that you'd use, note passing in the parsed JSON daa
var myClass = new MyClass(jsonResponse);
console.log(myClass instanceof MyClass); // true
现场示例:
// The "class"
var MyClass = function(data) {
// Create all the allowed properties
this.key = '123';
// Seal the instance so others can't be created
Object.seal(this);
// If data was supplied, apply it
if (data) {
$.extend(this, data);
}
};
var jsonResponse = {
key: "456"
};
// The instance that you'd use, note passing in the parsed JSON daa
var myClass = new MyClass(jsonResponse);
console.log(myClass instanceof MyClass); // true
console.log(myClass.key); // "456"
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
jsonResponse
如果包含MyClass
不允许的属性,则会引发错误,因为尝试在密封对象上创建新属性会引发错误。你在评论中说过这就是你想要的(这是有道理的)。
如果这不是您想要的,您可以编写自己的函数来复制属性,而不是使用$.extend
:
function applyData(obj, data) {
var own = Object.prototype.hasOwnProperty.bind(obj);
Object.keys(data).filter(own).forEach(function(key) {
obj[key] = data[key];
});
}
(或者,in
如果您想允许设置继承的属性——例如,访问器属性——,请使用检查。)
(您可以只if
在forEach
回调中使用 an 而不是.filter(own)
。)
然后使用该函数而不是$.extend
.
现场示例:
// The function to apply the data
function applyData(obj, data) {
var own = Object.prototype.hasOwnProperty.bind(obj);
Object.keys(data).filter(own).forEach(function(key) {
obj[key] = data[key];
});
}
// The "class"
var MyClass = function(data) {
// Create all the allowed properties
this.key = '123';
// Seal the instance so others can't be created
Object.seal(this);
// If data was supplied, apply it
if (data) {
applyData(this, data);
}
};
var jsonResponse = {
key: "456",
extra: "will be ignored"
};
// The instance that you'd use, note passing in the parsed JSON daa
var myClass = new MyClass(jsonResponse);
console.log(myClass instanceof MyClass); // true
console.log(myClass.key); // "456"
console.log(myClass.extra); // undefined
但是你犯错误的方法是有道理的。
推荐阅读
- seo - 添加本地业务架构时,同一页面的不同标记中具有相同的@type业务是否错误?
- wso2is - WSO2 身份服务器:WSO2 是否支持 SSIS 和 DID?
- azure-iot-hub - 调用 Azure IoT Direct 方法时 URL 的 Api 版本
- go - 我有查询如何将查询转换为 dsl
- state - 在 AnyLogic 中,如何在执行 CraneProgram 后将起重机返回到自动模式(空闲状态)?
- pandas - 两个多索引切片上的数据帧乘法()操作上的不正确广播(?)
- python-3.x - ImportError:在 MacOS 上安装 Coral
- angular - 有人可以给我指一个网络图,描述 Azure 中 vm、nic、nsg、rg、vnet、子网、公共 ip、私有 ip 之间的关系吗?
- oracle - Oracle plsql 错误 PLS-00642:SQL 语句中不允许本地集合类型
- python - 为什么virtualenv上的`pip install`会引发“无法执行'--user'安装”?