From:  Sebastian Zartner <sebastianzartner@gmail.com>
Date:  06 Mar 2017 16:47:06 Hong Kong Time
Newsgroup:  news.mozilla.org/mozilla.dev.mdc
Subject:  

Re: Object.keys Method in Javascript - Some doubts, clarifications && a small proposal

NNTP-Posting-Host:  63.245.214.181

Forwarding this message to the MDC mailing list, as I'm too busy today to
review this and will go on vacation tomorrow.

Sebastian

On 6 March 2017 at 08:56, Sricharan Krishnan 
wrote:

> Dear Sebastian,
>
> Thank you for your revert. Yup so, most of what you have said have been
> cleared up. Thus an updated version of the polyfill would be probably as
> below:
>
> Object.keys = Object.keys || function(obj) {*    //starts off with the type check requirements to have this function/method**    //working, if there is a failure, this process will not happen.*
>     if(typeof obj !== "function" && (typeof obj !== "object" || obj === null)) {
>         throw new TypeError("Object.keys is being called for a non null object");
>     }
>
>     var result = [];
>
>     for (property in obj) {
>         *//check condition to see if an object has its own property and just to**        //make sure that its enumerable in nature, only then pass it to the **        //result array;*
>         if(Object.prototype.hasOwnProperty.call(obj, property) && Object.prototype.propertyIsEnumerable.call(obj, property)) {
>             result.push(property);
>         }
>     }
> *    //finally to end this process, return the result array with the**    //properties received from the for in loop process;*
>     return result;
> };
>
> But here is the part that I still dont seem to understand, the first fold
> that we were talking about:
>
>    - So I get the part where the object is returned post {toString: null}.
>    - And for my understanding, it unfortunately stops there.
>    - I am writing out to a mailing list -> Learning Center and India List.
>    - Trust they would be able to explain this to me in the way that I can
>    understand.
>
> If there is another way (perhaps break this step by step, with the
> objectives in mind while writing this polyfill), it would be really
> appreciated. Also, if I do have something coming up with CSS, will contact
> you.
>
> *CC @Learning Center | @ Community Inda - looking forward to your support.*
>
> Thank you.
> With Kind Regards,
> *Sricharan Krishnan | sricharan.krishnan@gmail.com
> *
> On Sunday 05 March 2017 07:29 PM, Sebastian Zartner wrote:
>
> Hi again Sricharan,
>
> while I wrote last time that you can ask me when you have questions about
> MDN contents, I'm rather involved in CSS than JS. So, it's better to ask
> them on the mdc mailing list instead, so you reach more people.
>
> Anyway, I'll try to answer your questions as good as I can.
>
>
> On 5 March 2017 at 09:01, Sricharan Krishnan  > wrote:
>
>> Dear Sebastian,
>>
>> Hello there, hope you are doing well.
>>
>> Well, this time I sure do like to get some clarifications on one of the
>> Methods in Javascript. This is with reference to the Object.keys method
>> that has been listed in the url : *https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
>> *
>>
>>    - Could explain to me in terms that could be as simple as possible to
>>    make things clear about why do we have this part in the polyfill?
>>
>> 	hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
>>         dontEnums = [
>>           'toString',
>>           'toLocaleString',
>>           'valueOf',hi
>>           'hasOwnProperty',
>>           'isPrototypeOf',
>>           'propertyIsEnumerable',
>>           'constructor'
>>         ],
>>         dontEnumsLength = dontEnums.length;
>>
>> The brackets around { toString: null } execute the code and return the
> object. propertyIsEnumerable() checks whether a property is returned
> within a for...in
> 
> loop. When toString is explicitly defined in an object,
> propertyIsEnumerable() must return true for it.
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe
> rence/Global_Objects/Object/propertyIsEnumerable#Browser_compatibility
> says that in Firefox 3.6 propertyIsEnumerable() incorrectly returned false,
> so I assume that's the reason.
> Though, a comment should be added above the code explaining that.
>
>> *Secondly, I dont understand why we are doing a type checking for a
>> function to be received in the parameter for the closure like below:*
>>
>> return function(obj) {
>>       if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) {
>>         throw new TypeError('Object.keys called on non-object');
>>       }
>>
>> This is because obj is the variable you pass as parameter to
> Object.keys(). You need to check whether this variable actually is an
> object, because Object.keys() only works on objects.
>
>>
>>    - *Third, I would like to propose a very simplified version of this
>>    polyfill based on the introductory portion for this particular method:*
>>
>> The *Object.keys()* method returns an array of a given object's own enumerable properties,
>> in the same order as that provided by a for...in  loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
>> *Suggested Polyfill:*
>> Object.keys = Object.keys || function(obj) {
>> 	if(typeof(obj) !== "object" || typeof(obj) === "null"){
>>
>> This misses the check for typeof obj !== function. Object.keys() also
> works on functions.
> Also note, typeof is an operator not a function, so you don't need the
> brackets.
>
>> 		throw new TypeError("Object.keys method is being called for a non-object");
>> 	}
>>
>> 	var result = [];
>> 	
>> 	if(typeof(obj) === "function") {
>> 		*//I had this portion checked out Moz FireFox and when I placed a function through this method, it just returned an**		//empty array, so thus the below code;*
>> 		return (result);
>> 	}
>>
>> That's incorrect, because functions in JavaScript are also objects
> ,
> that means they also can have properties. Try this:
> let test =  function() { return 0; }
> test.xyz = "foo";
> Then Object.keys() returns an array containing the string "foo".
>
>> 	for (var props in obj) {
>> 		*//The below if condition to check if a property in the object is its Own property**		//And if its enumerable, then push it to the result array;*
>>
>> 		if(Object.prototype.hasOwnProperty.call(obj, props) && Object.prototype.propertyIsEnumerable(obj, props)){
>> 			result.push(props);		
>> 		}
>>
>> This causes problems with the incorrect return value of
> Object.propertyIsEnumerable().
>
>> 	}
>>
>> 	//Finally, end this entire process by just returning the result array,
>> 	//which has all the properties gathered from the for in loop;
>> 	return (result);
>>
>> If I am not mistaked, the brackets are not required here.
>
>> }
>>
>> I am presently only a beginner, thus I would request you to kindly have
>> my suggestion perhaps placed through an expert to see if its ok, if so then
>> do go ahead and have this one placed on MDN for other people's reference.
>>
> Having said all this, I actually wonder why we still need the polyfill,
> because all browsers and other users agents support Object.keys() for
> many years now. But again, I'm not a JavaScript/ECMAScript expert myself,
> so feel free to post your questions and the polyfill to the mailing list to
> get a broader review.
>
>> Looking forward to your kind revert at your earliest and wishing you a
>> great day ahead.
>>
> Thank you! Have a great time!
> Sebastian
>
>