Skip to content

Commit

Permalink
Confirm the answer according to #5
Browse files Browse the repository at this point in the history
  • Loading branch information
aleen42 committed Jul 15, 2022
1 parent 10243cd commit df2ee0d
Showing 1 changed file with 54 additions and 9 deletions.
63 changes: 54 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,36 @@ Object.pick({a : 1, b : 2}, (v, k) => k !== 'b'); // => {a: 1}

### FAQ

1. When it comes to the prototype chain of an object, should the method pick or omit it? (The answer may change)
1. When it comes to the prototype chain of an object, should the method pick or omit it?

A: The implementation of [`_.pick`](https://lodash.com/docs/4.17.15#pick) and [`_.omit`](https://lodash.com/docs/4.17.15#omit) by Lodash has taken care about the chain. To keep the rule, we can pick off properties of the prototype, but can't omit them:
A: Consistent with destructuring: we can pick off properties of the prototype, but can't omit them.
```js
Object.pick({a : 1}, ['toString']); // => {toString: f}
// equivalent to the behavior
const {toString} = {a : 1};
toString; // => f toString() { [native code] }
Object.omit({a : 1}, ['toString']).toString; // => ƒ toString() { [native code] }
// equivalent to the behavior
const {toString, ...res} = {a : 1}
res.toString; // => ƒ toString() { [native code] }
```
The implementation of [`_.pick`](https://lodash.com/docs/4.17.15#pick) and [`_.omit`](https://lodash.com/docs/4.17.15#omit) by Lodash has also taken care about the chain.
The same rule applies to `__proto__` event if it has been [deprecated](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto) because the proposal should be pure enough to not specify a special logic to eliminate deprecated properties:
```js
Object.pick({}, ['__proto__']); // => {__proto__: {...}}
Object.omit({}, ['__proto__']).__proto__; // => {...}
// equivalent to the behavior
const {__proto__} = {};
__proto__; // => {...}
Object.omit({}, ['__proto__']).__proto__; // => {...}
// equivalent to the behavior
const {__proto__, ...res} = {}
res.__proto__; // => {...}
```
In some opinions, picking off or omitting properties from the prototype chain should make the method more extendable:
Expand All @@ -179,39 +195,68 @@ Object.pick({a : 1, b : 2}, (v, k) => k !== 'b'); // => {a: 1}
2. What is the type of returned value?
A: All these methods should return plain objects:
A: Consistent with destructuring: should return plain objects.
```js
Object.pick([]); // => {}
Object.pick([]); // => {}
Object.omit([]); // => {}
Object.pick(new Map()); // => {}
Object.pick(new Map()); // => {}
Object.omit(new Map()); // => {}
// equivalent to the behavior
const {...res} = [];
res instanceof Array; // => false
const {...res} = new Map();
res instanceof Map; // => false
const {...res} = new Set();
res instanceof Set; // => false
```
3. How to handle `Symbol`?
A: `Symbol` should just be considered as properties within `Symbol` keys, and they should obey the rules mentioned above:
A: Consistent with destructuring.
```js
Object.pick([], [Symbol.iterator]); // => {Symbol(Symbol.iterator): f}, pick off from the prototype
// equivalent to the behavior
const {[Symbol.iterator] : iter} = [];
iter; // => Symbol(Symbol.iterator): f
Object.omit([], [Symbol.iterator]); // => {}, plain objects
// equivalent to the behavior
const {[Symbol.iterator] : iter, ...res} = [];
res instanceof Array; // => false
const symbol = Symbol('key');
Object.omit({a : 1, [symbol]: 2}, [symbol]); // => {a : 1}
// equivalent to the behavior
const {[symbol] : _, ...res} = {a : 1, [symbol]: 2};
res; // => {a : 1}
Object.prototype[symbol] = 'test'; // override prototype
Object.pick({}, [symbol]); // => {Symbol(key): "test"}, pick off from the prototype
Object.omit({}, [symbol])[symbol]; // => "test", cannot omit properties from the prototype
// equivalent to the behavior
const {[symbol] : sym, ...res} = {};
sym; // => 'test'
res[symbol]; // => 'test'
```
4. If some properties of an object are not accessible like throwing an error, can `Object.pick` or `Object.omit` operate such an object?
A: I suggest throwing the error wrapped by `Object.pick` or `Object.omit`, but it is **NOT the final choice**:
A: Consistent with destructuring: throw the error wrapped by `Object.pick` or `Object.omit`.
```js
Object.pick(Object.defineProperty({}, 'key', {
get() { throw new Error() }
get() { throw new Error(); }
}), ['key']);
// equivalent to the behavior
const o = Object.defineProperty({}, 'key', {
get() { throw new Error('custom'); }
});
try { const {key} = o; } catch (e) {
e.message // => 'custom'
}
```
The error stack will look like this:
Expand Down

0 comments on commit df2ee0d

Please sign in to comment.