Path: csiph.com!.POSTED.204-73-239-109.cust.centrio.cz!not-for-mail From: Cezary Tomczyk Newsgroups: comp.lang.javascript Subject: Re: Object.defineProperties Date: Sat, 6 May 2017 20:23:06 +0200 Organization: csiph.com Internet News Service Message-ID: References: <1943190.NgBsaNRSFp@PointedEars.de> <1592229.TLkxdtWsSY@PointedEars.de> <2032926.ElGaqSPkdT@PointedEars.de> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Sat, 6 May 2017 18:23:06 +0000 (UTC) Injection-Info: csiph.com; posting-host="204-73-239-109.cust.centrio.cz:109.239.73.204"; logging-data="9941"; mail-complaints-to="admin@kev009.com" User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 In-Reply-To: <2032926.ElGaqSPkdT@PointedEars.de> Xref: csiph.com comp.lang.javascript:33239 On 06/05/2017 16:43, Thomas 'PointedEars' Lahn wrote: > Cezary Tomczyk wrote: > >> On 05/05/2017 20:11, Thomas 'PointedEars' Lahn wrote: >>> Cezary Tomczyk wrote: >>>> On 05/05/2017 18:14, Thomas 'PointedEars' Lahn wrote: >>>>> Cezary Tomczyk wrote: >>>> [...] [...] >>> To begin with, you should have >>> >>> var _toString = {}.toString; >>> >>> function isTypeOf(obj, typeToCheck) { >>> if (arguments.length < 2) { >>> return false; >>> } >>> return _toString.call(obj).slice(8, -1).toLowerCase() === >>> typeToCheck.toLowerCase(); >>> } >> >> Tiny optimisation, but that's fine. :-) > > Tiny optimization with big impact, I think. It saves > > - 1 lookup along the scope chain up to the global object for “Object” > *every time the function is called* > > - 2 lookups along the prototype chain each for “prototype” and “toString” > *every time the function is called* > > and removes the dependency on a potentially non-initial value of > “Object.prototype” and “Object.prototype.toString”. That's true, but it is also important to mention that the impact is significant in case of hundred operations at the same time. >>>>>> The Object.defineProperties says about object, but function, array are >>>>>> also objects. That's why: >>>>>> >>>>>> if (typeof obj !== 'object' || obj === null) >>>>>> throw new TypeError('bad obj'); >>>>>> >>>>>> looks like a bug to me. >>>>> typeof [] === "object", so that is OK. (common misconception) >>>> >>>> In a sense of that [] is an object - yes, but I'd prefer to know that >>>> tested object is in fact an Array type. Operator instanceof looks >>>> promising, but I need to check it anyway. >>> >>> Array.isArray() exists (since ECMAScript Ed. 5). For general and own >>> (array) types, I am using “instanceof” or “constructor”. Most of the >>> time, though, duck typing instead (“quack” ;-)). >> >> Ah, right, I forgot about Array.isArray() :) > > Be sure to emulate it if it is not there. Yes, thanks. >> Finally I rewrote it a bit: >> >> var _toString = {}.toString; >> >> function isTypeOf(obj, typeToCheck) { >> var objectType; >> >> if (arguments.length !== 2) { > > This change does not make sense to me. “< 2” was clearer. Passing 1 argument doesn't make sense and that's why I've used !== 2. >> return false; >> } >> >> objectType = typeof obj; > > IMO, DRY demands declaration and initialization in one statement, if > possible. I did it on purpose. If argument will be !== 2 then it is not efficient to initialize anything before. >> if (typeToCheck === 'array' && Array.isArray(obj) >> || typeToCheck === 'null' && objectType === 'object' >> || typeToCheck === 'object' && objectType === 'object' >> || typeToCheck === 'number' && objectType === 'number' >> || typeToCheck === 'string' && objectType === 'string' >> || typeToCheck === 'boolean' && objectType === 'boolean' >> || typeToCheck === 'undefined' && objectType === 'undefined' >> || typeToCheck === 'symbol' && objectType === 'symbol' > > I would use parentheses to make clear what conditions belong together. That can be done :-) >> ) { >> return true; >> } >> >> return _toString.call(obj).slice(8, -1).toLowerCase() === >> typeToCheck.toLowerCase(); >> } > > The question remains: What is being *gained* by this comparably inefficient > precision instead of duck typing? _Not_ all things that *can* be done also > *should* be done. The gain is to get the real type (let me call it like that) of object. -- Cezary Tomczyk http://www.ctomczyk.pl/ https://www.aslint.org/ - Accessibility validation tool