--- title: Js tips I can't remember date: 2019-03-22 09:00:00 tags: - JavaScript category: tech keywords: - Javascript - ES2015 - ES6 --- ## `__proto__` VS `prototype` >`__proto__` is the actual object that is used in the lookup chain to resolve methods and others. `prototype` is the object that is used to build `__proto__` when creating an object with `new`. >The "cool kids" in JavaScript would generally pronounce `__proto__` as "**dunder proto**". [https://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript](https://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript) ```javascript ( new Foo ).__proto__ === Foo.prototype; // true ( new Foo ).prototype === undefined; // true ``` ## `{}` VS `Object.create(null)` `Object.create(null)` can create a *'pure'* empty object that is without the delegation to `Object.prototype`. ```javascript let obj1 = {}; let obj2 = Object.create(null); console.log(obj1.__proto__); // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …} console.log(obj2.__proto__); // undefined ``` ## Computed Property Names ES6 adds computed property names, which is helpful when declaring objects using the object-literal syntax. ```javascript var prefix = "foo"; var myObject = { [prefix + "bar"]: "hello", [prefix + "baz"]: "world" }; myObject["foobar"]; // hello myObject["foobaz"]; // world ``` ## Dangerous `Function.prototype.name` comparison Sometimes we may spectify a function by comparing the function name: ```javascript function Foo() {}; let foo = new Foo(); if (foo.constructor.name === 'Foo') { console.log("'foo' is an instance of 'Foo'"); } else { console.log('Oops!'); } ``` It may behave unexpectedly after building because most build tools compress the code to forms like: ```javascript function a() {}; let b = new a(); if (b.constructor.name === 'Foo') { console.log("'foo' is an instance of 'Foo'"); } else { console.log('Oops!'); } ``` ## A more robust way of performing object property check Normally we use `hasOwnProperty()` checks to see if object has the property or not. But consider objects created by: ```javascript // this will not consult the [[Prototype]] chain let obj = Object.create(null) ``` Such object does not link to `Object.prototype`, thus `obj.hasOwnProperty(...)` would fail and raise error. We can use a more robust way to perform property check: ```javascript Object.prototype.hasOwnProperty.call(obj,"a") //false ``` Or: ```javascript // this will check the current object or any higher level of the [[Prototype]] chain "a" in obj ``` ## `for...in` vs `for...of` The `for..in` loop iterates over the list of enumerable properties on an object (including its `[[Prototype]]` chain).The `for...of` iterate over the values directly instead of the array indices (or object properties). It asks built-in or custom `@@iterator` of the thing to be iterated. ```javascript let arr = ['a', 'b', 'c'] arr.name = 'foo' arr // ["a", "b", "c", name: "foo"] for (key in arr) console.log(key) // 0 1 2 name for (value of arr) console.log(value) // a b c ``` ## "(Prototypal) Inheritance" When writing "prototype style" code like implementing Parent-Child class inheritance: ```javascript function Foo(name) { this.name = name; } Foo.prototype.myName = function() { return this.name; }; function Bar(name,label) { Foo.call( this, name ); this.label = label; } // Then trying to build a family with Foo and Bar // ... ``` A common mis-conception/confusion here is that either of the following approaches would also work, but they do not work as you'd expect: ```javascript // doesn't work like you want! Bar.prototype = Foo.prototype; // works kinda like you want, but with // side-effects you probably don't want :( Bar.prototype = new Foo(); ``` the right way is: ```javascript // "make a new 'Bar dot prototype' object that's linked to 'Foo dot prototype'." // pre-ES6 // throws away default existing `Bar.prototype` Bar.prototype = Object.create( Foo.prototype ); // ES6+ // modifies existing `Bar.prototype` Object.setPrototypeOf( Bar.prototype, Foo.prototype ); ``` **reference**: [You-Dont-Know-JS: "(Prototypal) Inheritance"](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch5.md#prototypal-inheritance)