Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #33169 > unrolled thread

Object.defineProperties

Started byCezary Tomczyk <cezary.tomczyk@gmail.com>
First post2017-05-03 08:36 +0200
Last post2017-05-05 18:24 +0200
Articles 9 on this page of 29 — 4 participants

Back to article view | Back to comp.lang.javascript


Contents

  Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-03 08:36 +0200
    Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-03 10:14 +0200
      Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-03 10:59 +0200
        Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-03 12:36 +0200
          Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-03 18:47 +0200
            Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-05 18:18 +0200
      Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-05 18:14 +0200
        Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-05 19:37 +0200
          Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-05 20:11 +0200
            Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-06 15:26 +0200
              Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-06 16:43 +0200
                Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-06 20:23 +0200
                  Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-06 22:21 +0200
                    Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-06 23:19 +0200
                      Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-07 02:40 +0200
              Re: Object.defineProperties Stefan Weiss <krewecherl@gmail.com> - 2017-05-06 22:37 +0200
                Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-06 23:05 +0200
                  Re: Object.defineProperties Stefan Weiss <krewecherl@gmail.com> - 2017-05-07 00:29 +0200
                    Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-07 10:06 +0200
                      Re: Object.defineProperties Stefan Weiss <krewecherl@gmail.com> - 2017-05-08 00:50 +0200
                        Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-08 13:17 +0200
                  Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-07 02:37 +0200
                    Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-07 09:42 +0200
                      Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-07 17:11 +0200
                        Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-07 20:08 +0200
          Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-05 20:59 +0200
            Re: Object.defineProperties John G Harris <niam@jghnorth.org.uk.invalid> - 2017-05-06 10:35 +0100
    Re: Object.defineProperties Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2017-05-05 08:32 +0200
    Re: Object.defineProperties Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-05-05 18:24 +0200

Page 2 of 2 — ← Prev page 1 [2]


#33254

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2017-05-08 13:17 +0200
Message-ID<oepk4v$kml$1@csiph.com>
In reply to#33253
On 08/05/2017 00:50, Stefan Weiss wrote:
> Cezary Tomczyk wrote:
>> So, Object.assign does shallow copy, not deep copy. My goal , by having
>> "extend" function in that case, is to do deep copy.
>>
>> If I do extend({}, o); then new object will have his own data and changes
>> made on new object must not reflect on the source object.
>
> Okay, that makes sense. I thought you were saying that the action of
> Object.assign() itself caused the source object to be modified.
>
>>     function extend(target, source) {
>>         var output = target;
>>
>>         function processProperty(key) {
>>             if (isTypeOf(source[key], 'object')) {
>>                 output[key] = {};
>>                 extend(output[key], source[key]);
>>             } else if (isTypeOf(source[key], 'array')) {
>>                 output[key] = source[key].slice(0);
>>             } else {
>>                 output[key] = source[key];
>>             }
>>         }
>>
>>         Object.keys(source).forEach(processProperty);
>>
>>         return output;
>>     }
>
> Without testing this myself, I can see a potential problem: an array in the
> source object could contain objects as elements. Your extend() function does
> a shallow copy on arrays, so modifying objects in the target array will
> affect both the source and the target.

Since my last post I rewrote it to:

     function extend(destination, source) {
         var property,
             src;

         function cloneArray(a) {
             return Object.assign({}, a);
         }

         for (property in source) {

             if (Object.prototype.hasOwnProperty.call(source, property)) {
                 src = source[property];

                 if (isTypeOf(src, 'object')) {
                     destination[property] = destination[property] || {};
                     extend(destination[property], src);
                 } else if (Array.isArray(src)) {
                     destination[property] = src.map(cloneArray);
                 } else if (getTypeOf(src) === 'date') {
                     destination[property] = new Date(src.valueOf());
                 } else if (getTypeOf(src) === 'regexp') {
                     destination[property] = new RegExp(src);
                 } else {
                     destination[property] = source[property];
                 }
             }

         }
         return destination;
     }

Of course, this doesn't cover all scenarios, but at least some major 
cases that I need.

> Apart from that, I still don't quite see the use for the isTypeOf()
> function... what's wrong with this:
>
>     if (Array.isArray(source[key])) {
>         // clone array (and recurse)
>     } else if (typeof source[key] == "object" && source[key] !== null) {
>         // clone object (and recurse)
>     } else {
>         // copy scalar values (and null)
>     }

There are even more cases that I've discovered while writing unit tests. 
I gave up and simplified to:

     var _toString = {}.toString;

     function getTypeOf(obj) {
         if (arguments.length !== 1) {
             return false;
         }

         return _toString.call(obj).slice(8, -1).toLowerCase();
     }

     function isTypeOf(obj, typeToCheck) {
         var type;

         if (arguments.length < 2) {
             throw new TypeError('[isTypeOf] requires two arguments'); 
// The error message will have more precise data as Thomas suggested
         }

         type = typeToCheck.toLowerCase();

         return getTypeOf(obj) === type;
     }

> For the sake of completeness, I'd like to amend my earlier statement:
> The `typeof` operator, `Array.isArray()`, *and strict comparisons* are
> usually all that's needed.

This would not be enough. For example, if you do typeof Date or RegExp 
object you will get "object" in result. And that is not what I want. 
Because of that I think using "toString" here is fine. Even, if there 
are edge cases, at the moment I think this is an acceptable solution. 
Unless there will be no better solution ;-)

> Also for the sake of completeness, not all objects can be cloned 1:1 so that
> the they are 100% independent and disconnected. Simple data container
> objects should be fine, though.

>> However, when I run it in PhantomJS 2.1.1 (Mac OS X) then it throws exception:
>>
>> "TypeError: Requested keys of a value that is not an object. in object.js
>> (line 9)"
>>
>> While I understand that "source" is passed as a non-object then I can't find
>> out what's causing it. At least debugging PhantomJS is a bit hard.
>
> Sorry, I don't have enough experience with PhantomJS to help with that. I
> suggested it for my current project, but was rejected. Their mailing list

Interesting, but I do not see more reliable way of executing tests in 
browser environment. I mean, you can use browser itself and execute 
manually, but that's not the point. I know also that there are some fake 
DOM solution for NodeJS, but I have no experience with that. Anyway, 
it's an off-topic subject :-)

> may be worth a try: https://groups.google.com/forum/#!forum/phantomjs

Thanks. I've handled the problem.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/
https://www.aslint.org/ - Accessibility validation tool

[toc] | [prev] | [next] | [standalone]


#33245

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2017-05-07 02:37 +0200
Message-ID<38321860.ZmDeoRnzTM@PointedEars.de>
In reply to#33242
Cezary Tomczyk wrote:

>      function isTypeOf(obj, typeToCheck) {
>          var type;
> 
>          if (arguments.length < 2) {
>              throw new Error('[isTypeOf] requires two arguments');
>          }

You should throw a TypeError or a custom-typed exception (I throw 
object.js:jsx.InvalidArgumentError for such).

The message is confusing (“Is ‘isTypeOf’ the element of a one-element 
array?”)
 
-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#33247

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2017-05-07 09:42 +0200
Message-ID<oemj5r$1frd$1@csiph.com>
In reply to#33245
On 07/05/2017 02:37, Thomas 'PointedEars' Lahn wrote:
> Cezary Tomczyk wrote:
>
>>      function isTypeOf(obj, typeToCheck) {
>>          var type;
>>
>>          if (arguments.length < 2) {
>>              throw new Error('[isTypeOf] requires two arguments');
>>          }
>
> You should throw a TypeError or a custom-typed exception (I throw
> object.js:jsx.InvalidArgumentError for such).

Nice tip. I will use:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError

However, optional argument 'lineNumber' there is a bit weird to me as I 
don't know where the specified fragment of code will be in a production 
version (after minification) and therefore I can't pass there a line number.

> The message is confusing (“Is ‘isTypeOf’ the element of a one-element
> array?”)

The purpose of that message is to tell you where the message happened, 
here the '[isTypeOf]' refers to function name, and what happened, here 
is a message that 'requires two arguments'.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/
https://www.aslint.org/ - Accessibility validation tool

[toc] | [prev] | [next] | [standalone]


#33249

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2017-05-07 17:11 +0200
Message-ID<1783967.oMNUckLgyt@PointedEars.de>
In reply to#33247
Cezary Tomczyk wrote:

> On 07/05/2017 02:37, Thomas 'PointedEars' Lahn wrote:
>> Cezary Tomczyk wrote:
>>>      function isTypeOf(obj, typeToCheck) {
>>>          var type;
>>>
>>>          if (arguments.length < 2) {
>>>              throw new Error('[isTypeOf] requires two arguments');
>>>          }
>>
>> You should throw a TypeError or a custom-typed exception (I throw
>> object.js:jsx.InvalidArgumentError for such).
> 
> Nice tip. I will use:
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
> 
> However, optional argument 'lineNumber' there is a bit weird to me as I
> don't know where the specified fragment of code will be in a production
> version (after minification) and therefore I can't pass there a line
> number.

It is optional and proprietary anyway.

But, if available, you can obtain the URI and line number from the “stack” 
property and set them later.  (This is where custom-typed exceptions come 
in.)
 
>> The message is confusing (“Is ‘isTypeOf’ the element of a one-element
>> array?”)
> 
> The purpose of that message is to tell you where the message happened,
> here the '[isTypeOf]' refers to function name, and what happened, here
> is a message that 'requires two arguments'.

I *know* what it is *supposed* to tell.  It is nevertheless confusing to the 
person reading it.  The message should not require such an explanation.

It should also say more than “requires two arguments” because the next 
question of the developer would be “What arguments does it require, then?”.

See also jsx.InvalidArgumentError; currently

<https://github.com/PointedEars/JSX/blob/master/object.js#L3924-L3947>

Usage example:

<https://github.com/PointedEars/JSX/blob/master/object.js#L2669-L2671>
 
-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#33251

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2017-05-07 20:08 +0200
Message-ID<oennqo$29om$1@csiph.com>
In reply to#33249
On 07/05/2017 17:11, Thomas 'PointedEars' Lahn wrote:
> Cezary Tomczyk wrote:
>
>> On 07/05/2017 02:37, Thomas 'PointedEars' Lahn wrote:
>>> Cezary Tomczyk wrote:
>>>>      function isTypeOf(obj, typeToCheck) {
>>>>          var type;
>>>>
>>>>          if (arguments.length < 2) {
>>>>              throw new Error('[isTypeOf] requires two arguments');
>>>>          }
>>>
>>> You should throw a TypeError or a custom-typed exception (I throw
>>> object.js:jsx.InvalidArgumentError for such).
>>
>> Nice tip. I will use:
>> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
>>
>> However, optional argument 'lineNumber' there is a bit weird to me as I
>> don't know where the specified fragment of code will be in a production
>> version (after minification) and therefore I can't pass there a line
>> number.
>
> It is optional and proprietary anyway.
>
> But, if available, you can obtain the URI and line number from the “stack”
> property and set them later.  (This is where custom-typed exceptions come
> in.)

Thank you. I am going to use it in that way.

>>> The message is confusing (“Is ‘isTypeOf’ the element of a one-element
>>> array?”)
>>
>> The purpose of that message is to tell you where the message happened,
>> here the '[isTypeOf]' refers to function name, and what happened, here
>> is a message that 'requires two arguments'.
>
> I *know* what it is *supposed* to tell.  It is nevertheless confusing to the
> person reading it.  The message should not require such an explanation.
>
> It should also say more than “requires two arguments” because the next
> question of the developer would be “What arguments does it require, then?”.

And then, if available, developer may look at the documentation. ;-)

> See also jsx.InvalidArgumentError; currently
>
> <https://github.com/PointedEars/JSX/blob/master/object.js#L3924-L3947>
>
> Usage example:
>
> <https://github.com/PointedEars/JSX/blob/master/object.js#L2669-L2671>

But I agree that the error message should be more precise. One of the 
most annoying thing is to get unclear error message.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/
https://www.aslint.org/ - Accessibility validation tool

[toc] | [prev] | [next] | [standalone]


#33227

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2017-05-05 20:59 +0200
Message-ID<2709844.CbtlEUcBR6@PointedEars.de>
In reply to#33223
Cezary Tomczyk wrote:

> On 05/05/2017 18:14, Thomas 'PointedEars' Lahn wrote:
>> typeof function () {} === "function", so that is not OK in theory;
>> however, one might decide that it is not OK to modify function objects.
> 
> Functions are objects so they can be extended like any other objects.

I am not sure that is the reason.  ISTM that most importantly, them being 
objects allows for references to them to be assigned and passed.  The latter 
would be useful for an event-driven application.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#33232

FromJohn G Harris <niam@jghnorth.org.uk.invalid>
Date2017-05-06 10:35 +0100
Message-ID<756rgc11jc7v2aiavsmb2atqtm1ae6m26l@4ax.com>
In reply to#33227
On Fri, 05 May 2017 20:59:56 +0200, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:

>Cezary Tomczyk wrote:
>
>> On 05/05/2017 18:14, Thomas 'PointedEars' Lahn wrote:
>>> typeof function () {} === "function", so that is not OK in theory;
>>> however, one might decide that it is not OK to modify function objects.
>> 
>> Functions are objects so they can be extended like any other objects.
>
>I am not sure that is the reason.  ISTM that most importantly, them being 
>objects allows for references to them to be assigned and passed.  The latter 
>would be useful for an event-driven application.

It's values that are assigned and passed, not references. That's why
typeof returns "function", not "reference to function"

  John

[toc] | [prev] | [next] | [standalone]


#33206

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2017-05-05 08:32 +0200
Message-ID<oeh6ao$esg$1@csiph.com>
In reply to#33169
On 05/05/2017 04:39, Stefan Ram wrote:
> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>> Cezary Tomczyk <cezary.tomczyk@gmail.com> writes:
>>> Native built-in Object.defineProperties method allows me to add
>>> properties to a function as the function is an object.
>> The Web gives:
>> function isObject(val) {
>>    if (val === null) { return false;}
>>    return ( (typeof val === 'function') || (typeof val === 'object') );
>> }
>> . The above might not work with host objects, which might
>> have even other types.
>
>   However, according to Flanagan, a host object may not
>   return »undefined«, »boolean«, »number«, or »string« as
>   its type. So, another way to check whether something is
>   an object might be to check that its type is not one
>   of those.

Yes, but typeof for [] will still returns "object".

One more thing. Regarding:

let a = new String( "abc" );

console.log( Object.prototype.toString.call( a ) );

Object.defineProperty
( a, Symbol.toStringTag, { get: function() { return "Number"; }});

console.log( Object.prototype.toString.call( a ) );

if typing "a instanceof String" then there is "true". So, perhaps 
instanceof is the way of checking the type of object instead of 
Object.prototype.toString.call or typeof or Object.defineProperty[...]

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/
https://www.aslint.org/ - Accessibility validation tool

[toc] | [prev] | [next] | [standalone]


#33221

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2017-05-05 18:24 +0200
Message-ID<13239182.tv2OnDr8pf@PointedEars.de>
In reply to#33169
Stefan Ram wrote:

> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>Cezary Tomczyk <cezary.tomczyk@gmail.com> writes:
>>>Native built-in Object.defineProperties method allows me to add
>>>properties to a function as the function is an object.
>>The Web gives:
>>function isObject(val) {
>>    if (val === null) { return false;}
>>    return ( (typeof val === 'function') || (typeof val === 'object') );
>>}
>>. The above might not work with host objects, which might
>>have even other types.
> 
>   However, according to Flanagan, a host object may not
>   return »undefined«, »boolean«, »number«, or »string« as
>   its type. So, another way to check whether something is
>   an object might be to check that its type is not one
>   of those.

The same as you continue to neglect to cite your sources properly, 
"Flanagan" neglects to mention that he is referring to more recent editions 
of the ECMAScript Language Specification there, and that some implementors 
did not care.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.javascript


csiph-web