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


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

Overwriting existing fucntion

Started byAndrew Poulos <ap_prog@hotmail.com>
First post2015-10-19 12:12 +1100
Last post2015-10-19 13:29 -0700
Articles 11 — 4 participants

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


Contents

  Overwriting existing fucntion Andrew Poulos <ap_prog@hotmail.com> - 2015-10-19 12:12 +1100
    Re: Overwriting existing fucntion Andrew Poulos <ap_prog@hotmail.com> - 2015-10-19 13:57 +1100
    Re: Overwriting existing fucntion Stefan Weiss <krewecherl@gmail.com> - 2015-10-19 05:04 +0200
      Re: Overwriting existing fucntion Stefan Weiss <krewecherl@gmail.com> - 2015-10-19 13:14 +0200
    Re: Overwriting existing fucntion Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-10-19 19:49 +0200
      Re: Overwriting existing fucntion Andrew Poulos <ap_prog@hotmail.com> - 2015-10-20 10:18 +1100
        Re: Overwriting existing fucntion Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-10-20 02:17 +0200
      Re: Overwriting existing fucntion Stefan Weiss <krewecherl@gmail.com> - 2015-10-21 19:47 +0200
        Re: Overwriting existing fucntion Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-10-21 21:40 +0200
          Re: Overwriting existing fucntion Stefan Weiss <krewecherl@gmail.com> - 2015-10-22 03:04 +0200
    Re: Overwriting existing fucntion Danny <dann90038@gmail.com> - 2015-10-19 13:29 -0700

#28839 — Overwriting existing fucntion

FromAndrew Poulos <ap_prog@hotmail.com>
Date2015-10-19 12:12 +1100
SubjectOverwriting existing fucntion
Message-ID<CbCdnUFUDeXC3rnLnZ2dnUU7-amdnZ2d@westnet.com.au>
I'm using a 3rd party elearning product that produces web pages. The 
product allows me to add "custom" code to a page.

I need to "overwrite" one of the functions that the product produces 
with one of my own. Custom code seems to always get added before their 
code eg.

<script>
function action70 {
   // my customised function
}

...
function action70 {
   // their function
}
...
</script>

This means that mine gets "overwritten" so I tried using

function ap() {	
   function action70(){
     // my customised function
   }
}
if (window.addEventListener) {
	window.addEventListener("load", ap);
}

to get my function to "overwrite" the existing one but only their one 
ever gets triggered. How can I add my function before theirs and still 
have my one trigger?


Andrew Poulos

[toc] | [next] | [standalone]


#28840

FromAndrew Poulos <ap_prog@hotmail.com>
Date2015-10-19 13:57 +1100
Message-ID<COudnQhlS8ycwbnLnZ2dnUU7-KWdnZ2d@westnet.com.au>
In reply to#28839
On 19/10/2015 12:12 PM, Andrew Poulos wrote:
> I'm using a 3rd party elearning product that produces web pages. The
> product allows me to add "custom" code to a page.
>
> I need to "overwrite" one of the functions that the product produces
> with one of my own. Custom code seems to always get added before their
> code eg.
>
> <script>
> function action70 {
>    // my customised function
> }
>
> ...
> function action70 {
>    // their function
> }
> ...
> </script>
>
> This means that mine gets "overwritten" so I tried using
>
> function ap() {
>    function action70(){
>      // my customised function
>    }
> }
> if (window.addEventListener) {
>      window.addEventListener("load", ap);
> }
>
> to get my function to "overwrite" the existing one but only their one
> ever gets triggered. How can I add my function before theirs and still
> have my one trigger?

I just tried this

var action70;

function ap() {
    action70 = function(){
      // my customised function
    }
}
if (window.addEventListener) {
      window.addEventListener("load", ap);
}

and now my function triggering but I'm unsure why its working. Why does 
the first way not work and the second work?

Andrew Poulos

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


#28841

FromStefan Weiss <krewecherl@gmail.com>
Date2015-10-19 05:04 +0200
Message-ID<n01mji$k3l$1@news.albasani.net>
In reply to#28839
On 2015-10-19 03:12, Andrew Poulos wrote:
> I need to "overwrite" one of the functions that the product produces 
> with one of my own. Custom code seems to always get added before their 
> code eg.
...
> function ap() {	
>    function action70(){
>      // my customised function
>    }
> }
> if (window.addEventListener) {
> 	window.addEventListener("load", ap);
> }

This doesn't work because action70() in this example is not visible
outside of ap(); it cannot overwrite a global function. Depending on
what exactly the fixed application code does, and which user agents have
to be supported, you could try using `Object.defineProperty()`:

    ////// your code /////////////

    function my_action70 () {
        console.log("custom function");
    }

    Object.defineProperty(window, "action70", { value: my_action70 });

    ////// fixed app code /////////

    function action70 () {
        console.log("original function");
    }

    ////// test ///////////////////

    action70();   // "custom function"


- stefan


PS, just saw your reply - the reason why your second version works is
because it creates a property on the global object - i.e., action70() is
now visible outside of ap().

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


#28842

FromStefan Weiss <krewecherl@gmail.com>
Date2015-10-19 13:14 +0200
Message-ID<n02jb7$qrl$1@news.albasani.net>
In reply to#28841
On 2015-10-19 05:04, Stefan Weiss wrote:
> Object.defineProperty(window, "action70", { value: my_action70 });

Actually, scratch that. If a simple `action70 = ...` works in the
context you describe, then that's all you need. It would be cleaner to
explicitly set `window.action70` in your code, or to declare a global
`action70` variable (if you can), so that the purpose of the assignment
is immediately obvious to the reader.

`Object.defineProperty()` only has an advantage if the application code
also tries to set `window.action70` or assigns to `action70` without
declaring it, which sounds unlikely from what you wrote.


- stefan

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


#28843

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-10-19 19:49 +0200
Message-ID<2283142.7jlluFck8S@PointedEars.de>
In reply to#28839
Andrew Poulos wrote:

> I'm using a 3rd party elearning product that produces web pages. The
> product allows me to add "custom" code to a page.
> 
> I need to "overwrite" one of the functions that the product produces
> with one of my own. Custom code seems to always get added before their
> code eg.
> 
> […]
> function ap() {
>    function action70(){
>      // my customised function
>    }
> }
> if (window.addEventListener) {
> window.addEventListener("load", ap);
> }
> 
> to get my function to "overwrite" the existing one but only their one
> ever gets triggered.

This works insofar that it is proper executable code, but the event handler 
calls the event listener referred by “ap”, which declares a local function 
and then exits, so that the Function instance just created by the 
declaration is immediately available for garbage collection – functionally a 
no-op, it may even be optimized to function ap () {} or, further, the 
addEventListener() call may be optimized out.

> How can I add my function before theirs and still have my one trigger?

You cannot.  But (towards which you should have asked, see “X–Y problem”) 
you can overwrite their function afterwards by assigning a value to the same 
identifier, provided that they have not made the corresponding property 
read-only:

  document.addEventListener("load", function () { action70 = … }, false);

If the property is read-only but still configurable, you can make it 
writable again before that:

  Object.defineProperty(global, "action70", {
    writable: true,
    enumerable: true,   // or false
    configurable: true  // or false
  });

Properties resulting from variable declarations should not be configurable 
in the first place, so in that case you do not have to worry about read-
onlyness.

Different to what Stefan suggested, you should not be using “window” to 
refer to the global object, but if you need to make it explicit, “this” in 
the global execution context.  For example

  /* global context */
  var global = this;

  /* any context */
  document.addEventListener("load",
    function () { global.action70 = … }, false);

(A reference to the global object can also be obtained in other ways.)

Also, the host object referred to by “window” might not implement an 
“addEventListener()” method; “document” is safer, “document.body” is 
probably safest, given the history of the “load” event, but might not yet be 
available at this time (before the “body” element has been parsed).  
Consider using the “defer” attribute.  On the other hand, you appear to be 
using HTML5, so this difference might not of importance to you.  However, as 
in theory the document can be loaded before loading of the window content 
has been completed, using “document” or “document.body” instead might speed 
things up a little.

Note that this approach depends on the definition in W3C UI Events 
(formerly, W3C DOM Level 3 Events) that event listeners are added and 
executed in source code order.  If this needs to work where 
addEventListener() is not available (IE < 9 or IE 9 in Compatibility Mode), 
using window.attachEvent() instead of .addEventListener() does not suffice 
as, among other peculiarities, .attachEvent() does not observe addition 
order.

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

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


#28845

FromAndrew Poulos <ap_prog@hotmail.com>
Date2015-10-20 10:18 +1100
Message-ID<R8ydnSViU8ql57jLnZ2dnUU7-K-dnZ2d@westnet.com.au>
In reply to#28843
On 20/10/2015 4:49 AM, Thomas 'PointedEars' Lahn wrote:
> Andrew Poulos wrote:
>
>> I'm using a 3rd party elearning product that produces web pages. The
>> product allows me to add "custom" code to a page.
>>
>> I need to "overwrite" one of the functions that the product produces
>> with one of my own. Custom code seems to always get added before their
>> code eg.
>>
>> […]
>> function ap() {
>>     function action70(){
>>       // my customised function
>>     }
>> }
>> if (window.addEventListener) {
>> window.addEventListener("load", ap);
>> }
>>
>> to get my function to "overwrite" the existing one but only their one
>> ever gets triggered.
>
> This works insofar that it is proper executable code, but the event handler
> calls the event listener referred by “ap”, which declares a local function
> and then exits, so that the Function instance just created by the
> declaration is immediately available for garbage collection – functionally a
> no-op, it may even be optimized to function ap () {} or, further, the
> addEventListener() call may be optimized out.

This is the bit that caught me out. "function action70(){" is a local 
function even though a function with the same identifier exists in the 
global space.

>> How can I add my function before theirs and still have my one trigger?
>
> You cannot.  But (towards which you should have asked, see “X–Y problem”)
> you can overwrite their function afterwards by assigning a value to the same
> identifier, provided that they have not made the corresponding property
> read-only:
>
>    document.addEventListener("load", function () { action70 = … }, false);
>
> If the property is read-only but still configurable, you can make it
> writable again before that:
>
>    Object.defineProperty(global, "action70", {
>      writable: true,
>      enumerable: true,   // or false
>      configurable: true  // or false
>    });
>
> Properties resulting from variable declarations should not be configurable
> in the first place, so in that case you do not have to worry about read-
> onlyness.
>
> Different to what Stefan suggested, you should not be using “window” to
> refer to the global object, but if you need to make it explicit, “this” in
> the global execution context.  For example
>
>    /* global context */
>    var global = this;
>
>    /* any context */
>    document.addEventListener("load",
>      function () { global.action70 = … }, false);
>
> (A reference to the global object can also be obtained in other ways.)
>
> Also, the host object referred to by “window” might not implement an
> “addEventListener()” method; “document” is safer, “document.body” is
> probably safest, given the history of the “load” event, but might not yet be
> available at this time (before the “body” element has been parsed).
> Consider using the “defer” attribute.  On the other hand, you appear to be
> using HTML5, so this difference might not of importance to you.  However, as
> in theory the document can be loaded before loading of the window content
> has been completed, using “document” or “document.body” instead might speed
> things up a little.
>
> Note that this approach depends on the definition in W3C UI Events
> (formerly, W3C DOM Level 3 Events) that event listeners are added and
> executed in source code order.  If this needs to work where
> addEventListener() is not available (IE < 9 or IE 9 in Compatibility Mode),
> using window.attachEvent() instead of .addEventListener() does not suffice
> as, among other peculiarities, .attachEvent() does not observe addition
> order.

Thank you for such a comprehensive answer. If you ever published a book 
on scripting web pages I, for one, would buy a copy.

Andrew Poulos

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


#28846

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-10-20 02:17 +0200
Message-ID<1867226.5Pa8prDpYa@PointedEars.de>
In reply to#28845
Andrew Poulos wrote:

> On 20/10/2015 4:49 AM, Thomas 'PointedEars' Lahn wrote:
>> Andrew Poulos wrote:
>>> […]
>>> function ap() {
>>>     function action70(){
>>>       // my customised function
>>>     }
>>> }
>>> if (window.addEventListener) {
>>> window.addEventListener("load", ap);
>>> }
>>>
>>> to get my function to "overwrite" the existing one but only their one
>>> ever gets triggered.
>>
>> This works insofar that it is proper executable code, but the event
>> handler calls the event listener referred by “ap”, which declares a local
>> function and then exits, so that the Function instance just created by
>> the declaration is immediately available for garbage collection –
>> functionally a no-op, it may even be optimized to function ap () {} or,
>> further, the addEventListener() call may be optimized out.
> 
> This is the bit that caught me out. "function action70(){" is a local
> function even though a function with the same identifier exists in the
                                                                  ^^^^^^
> global space.
  ^^^^^^^^^^^^
Yes; in general: in the outer execution contexts.

It is easier to see if you think of a function declaration as a variable 
declaration with initialization in disguise:
 
  function ap ()
  {
    function action70 ()
    {
      // my customised function
    }
  }

is equivalent to

  var ap = function () {
    var action70 = function () {
      // my customised function
    };
  };

except that the original code is executed before all statements in the same 
execution context that are not declarations (misleadingly called “hoisting” 
elsewhere), and in source code order with other declarations in the same 
context.

You would not expect that “action70” or its value is available outside ap 
unless ap() returned the value, and the same is true for function 
declarations.

> Thank you for such a comprehensive answer. If you ever published a book 
> on scripting web pages I, for one, would buy a copy.

You are welcome.  Duly noted.

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

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


#28851

FromStefan Weiss <krewecherl@gmail.com>
Date2015-10-21 19:47 +0200
Message-ID<n08j45$cfc$1@news.albasani.net>
In reply to#28843
On 2015-10-19 19:49, Thomas 'PointedEars' Lahn wrote:
> Different to what Stefan suggested, you should not be using “window” to 
> refer to the global object, but if you need to make it explicit, “this” in 
> the global execution context.  For example
> 
>   /* global context */
>   var global = this;

This will not give you the global object, but rather the window object
again (actually, the window's WindowProxy object) in HTML5:

| A global object
|
| An object that provides the APIs that can be called by the code in
| scripts that use this settings object.
|
| Note: This is typically a Window object or a WorkerGlobalScope
| object. When a global object is an empty object, it can't do anything
| that interacts with the environment.
|
| If the global object is a Window object, then, in JavaScript, the
| ThisBinding of the global execution context for this script must
| be the Window object's WindowProxy object, rather than the global
| object. [ECMA262]
|
| Note: This is a willful violation of the JavaScript specification
| current at the time of writing (ECMAScript edition 5, as defined
| in section 10.4.1.1 Initial Global Execution Context, step 3). The
| JavaScript specification requires that the this keyword in the
| global scope return the global object, but this is not compatible
| with the security design prevalent in implementations as specified
| herein. [ECMA262]

http://www.w3.org/TR/html5/webappapis.html#global-object

Even before HTML5, I've never heard of a browser in which `window` in
the global context would be anything other than a host object giving
access to the global object's properties - barring non-document
contexts, shadowing, obsolete browsers, and bugs. Unless you're doing
something very unusual, the warning to not rely on `window` is unnecessary.


- stefan

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


#28852

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-10-21 21:40 +0200
Message-ID<37067801.r229cbFWdt@PointedEars.de>
In reply to#28851
Stefan Weiss wrote:

> On 2015-10-19 19:49, Thomas 'PointedEars' Lahn wrote:
>> Different to what Stefan suggested, you should not be using “window” to
>> refer to the global object, but if you need to make it explicit, “this”
>> in the global execution context.  For example
>> 
>>   /* global context */
>>   var global = this;
> 
> This will not give you the global object, but rather the window object
> again (actually, the window's WindowProxy object) in HTML5:

Nonsense.

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

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


#28853

FromStefan Weiss <krewecherl@gmail.com>
Date2015-10-22 03:04 +0200
Message-ID<n09cnk$7cu$1@news.albasani.net>
In reply to#28852
On 2015-10-21 21:40, Thomas 'PointedEars' Lahn wrote:
> Stefan Weiss wrote:
>>>   /* global context */
>>>   var global = this;
>> 
>> This will not give you the global object, but rather the window object
>> again (actually, the window's WindowProxy object) in HTML5:
> 
> Nonsense.

It's getting hard to take you seriously anymore. I quoted and linked the
relevant passage from the spec, for crying out lout. You can also easily
confirm it for yourself.

"Nonsense" must be your way of saying "I stand corrected".


- stefan

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


#28844

FromDanny <dann90038@gmail.com>
Date2015-10-19 13:29 -0700
Message-ID<85939d69-3e02-40f8-bcf4-260716cbe18a@googlegroups.com>
In reply to#28839
to Andrew Poulos

putting the function as a child function of another,
will simply make it a private function, in this case
of function/class "ap".

you could use a variable to use that "class" and 
then call the function, assuming is set as 
this.myaction70 = function(){....}

however, if you just need a namespace for it, simply
make an object, and have myaction70() as property/member
of that object


 var ap = {
 		   myaction70 : funtion(){ // something }
		   }
------------------------------------------------
 window.addEventListener("load",ap.myaction70,false);

[toc] | [prev] | [standalone]


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


csiph-web