![](/img/trans.png)
[英]Implementing a function to access an object's property versus accessing the property using dot notation, or bracket notation?
[英]In JavaScript, do there exist any ways to get a property of an object without using dot notation or bracket notation?
假设我有一个简单的 object a = {b: 2}
。 我知道有两种方法可以获取 a 的属性 b 的值:
点符号: ab // 2
和
括号表示法: a['b'] // 2
撇开实用性不谈,有没有办法在不使用这两种方法(圆点表示法和括号表示法)的情况下从 object a 中获取 b 的值? MDN 关于 Property Accessors 的页面只列出了这两种方法。
这只是我的好奇心。 我知道有一些晦涩的方法可以不带括号调用函数,例如
parseInt`5.1`
我想看看 Property 访问是否可能有类似的晦涩难懂的事情。
首先想到的是Object.values
const a = {b: 2} Object.values(a).forEach(v => { console.info(v) })
但是,您如何知道正在访问的密钥?
我想还有Object.entries()
const a = {b: 2} Object.entries(a).forEach(entry => { // entries are [key, value] arrays let value = entry.pop() let key = entry.pop() console.info(key, ':', value) })
注意:我使用Array.prototype.pop()
以免使用“括号表示法” 。
这与访问属性并不完全相同 ,但是如果您使用的是最新的JS(es6 +),它仍然是一种获取对象内容的偷偷摸摸的方法。 这些天,所有时髦的JS孩子都在这样做。
const { b } = a
console.log(b) // 2
这称为解构 ,它与对象和数组一起使用,您可以在此处了解更多信息: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
不要忘记Object.getOwnPropertyDescriptor()
:
const object1 = {
property1: 42
}
const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'property1');
console.log(descriptor1.value);//42
它不会搜索原型链,但是它可以处理立即属性,并且值得注意,因为您可以使用它来使递归函数搜索原型链:)
这是不使用圆点或括号表示法的 lodash ‘get’ 和 ‘set’ 的实现; 对于通过安全扫描很有用。
https://jsfiddle.net/5amtL8zx/17/
/* lodash implementation of 'get', 'set', and 'unset' without dot or bracket notation
* - supports getting and setting 'prop1.2' array element but not with brackets: 'prop1.[2]'
*/
isObjectKey = (obj, key) => {
return Object.getPrototypeOf(obj) === Object.prototype && /string|number/.test(typeof key);
}
isArrayNumber = (obj, key) => {
const isKey = /string|number/.test(typeof key), path = isKey ? String(key).split('.') : [], prop = isKey && path.length > 1 ? path.shift() : '';
return Object.getPrototypeOf(obj) === Array.prototype && isKey && !isNaN(prop);
}
isValid = (obj, key) => {
const isObj = isObjectKey(obj, key), isArr = isArrayNumber(obj, key);
return isObj || isArr;
}
define = (obj, key, value) => {
Object.defineProperty(obj, String(key), { value, writable: true, configurable: true, enumerable: true });
}
get = (obj, key, value) => {
if (!isValid(obj, key)) {
return undefined;
}
let path = String(key).split('.'), prop = path.shift(), result = new Map(Object.entries(obj)).get(prop);
return path.length && typeof result !== 'undefined' ? get(result, path.join('.'), value) : result || value;
}
set = (obj, key, value) => {
if (!isValid(obj, key)) {
return undefined;
}
let path = key.split('.'), prop = path.shift();
if (!(prop in obj)) {
define(obj, prop, {});
}
const result = get(obj, prop);
return path.length && isValid(result, path.join('.')) ? set(result, path.join('.'), value) : define(obj, prop, value);
}
unset = (obj, key) => {
if (!isValid(obj, key)) {
return undefined;
}
let path = key.split('.'), prop = path.shift();
if (!(prop in obj)) {
return undefined;
}
if (path.length) {
let result = get(obj, prop);
result = unset(result, path.join('.'));
set(obj, prop, result);
return obj;
} else {
const { [prop]: remove, ...rest } = obj;
return rest;
}
}
let obj = {};
set(obj, 'prop1.prop2', 'value1');
console.log(Object.entries(obj));
console.log(get(obj, 'prop1.prop2'));
const prop1 = get(obj, 'prop1');
set(prop1, 'prop2', 'value2');
console.log(get(obj, 'prop1.prop2'));
set(obj, 'prop3', [1, 2, 3]);
console.log(get(obj, 'prop3'));
console.log(get(obj, 'prop3.2'));
console.log(get(obj.prop3, 0));
set(obj, 'prop3.3', 4);
console.log(get(obj, 'prop3.3'));
set(obj, 'prop4', [{'name': 'Bob'}]);
console.log(get(obj, 'prop4.0'));
unset(obj, 'prop4.0.name')
console.log(get(obj, 'prop4.0'));
//[["prop1", {
// prop2: "value1"
//}]]
//"value1"
//"value2"
//[1, 2, 3]
//3
//1
//4
//{
// name: "Bob"
//}
//{ ... }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.