Redefine function's 'toString' and 'valueOf' - javascript

I defined a prototype function 'isElement' of Node and I want to make it works like 'div.isElement' return 'true'.
<div id="dom1">someText
<p>This is p1 of <span class="bold">dom1</span></p>
</div>
Node.prototype.isElement = (function(){
var result;
var fn = function(){
console.log(obj);
result = (this.nodeType == 1 ? true : false);
return result;
};
fn.toString = fn.valueOf = function(){
return result;
};
return fn;
})();
var dom1 = document.getElementById('dom1');
dom1.isElement(); //true
dom1.isElement; //true
If the 'dom1' never call the function 'isElement()',then 'dom1.isElement' return 'undefined'. I understand why it return 'undefined',but I want to know how to makes it return 'true' or 'false' when 'isElement()' never be called.
I just want to use it like:
if(dom1.isElement){//do something}
but not like:
if(dom1.isElement()){//do something}
waiting for answers , thanks.

As mentioned in the comments, the JavaScript language makes no guarantees that the DOM implementation provides the standard JS object facilities.
That said, if you have determined that your environment always supports these then a getter is called for in this case, effectively you can write a function which is called whenever a specific property value is requested.
Refer to MDN for the details :
Node.prototype.__defineGetter__('isElement',
function () { return this.nodeType === 1; });
Test it with your browser at http://jsfiddle.net/L5hBq/

You can add a property that has your function as the getter:
Object.defineProperty(Node.prototype, "isElement", {
get: function() {
var result = this.nodeType == 1;
return result;
}
});

Related

JavaScript: get to arguments object of callback

Fiddle here
I'm looking at making some very high level logic into helper functions for curiosity's sake. I would like to be able to execute a function with its parameters in the _if function without having to define something like _callback ahead of time? I feel like I'm missing something here.
var _if = function(predicate,callback){
if(predicate){
callback(); //callback(arguments) is not arguments for callback
}
};
var text = 'some text';
_if(1 > 0,function(){
console.log('hello world'); //hello world
});
_if(1 > 0,function(text){
console.log(text); //undefined
});
//define callback for this situation
var _callback = function(x){
console.log(x);
}
_if(1 > 0,function(){
_callback(text); //some text
});
Not sure what you want, but maybe this helps:
You can call your function like this too:
_if(1 > 0,_callback.bind(null,text)); //null is the value of this
_if(1,function(text){
console.log(text); //this way not undefined
}.bind(null,text));
1) This works because of the logic of JavaScript. In further versions you can use your version too if you use let text = 'some text'; - ref
2) null is the this value for the function, (more info here) but I think you can pass this too if you need to use it in the function (null will be automatically replaced in non-strict mode to the global object. That's why you can use window.colsole.log inside the function. - ref)
Why not just take the arguments to the callback function as extra parameters on _if?
var _if = function (predicate, callback, context) {
if (predicate) {
var callbackArgs = [].slice.call(arguments, 3);
callback.apply(context || null, callbackArgs);
}
};
// Usage:
_if(true, console.log, console, "text");

Function in JavaScript that can be called only once

I need to create a function which can be executed only once, in each time after the first it won't be executed. I know from C++ and Java about static variables that can do the work but I would like to know if there is a more elegant way to do this?
If by "won't be executed" you mean "will do nothing when called more than once", you can create a closure:
var something = (function() {
var executed = false;
return function() {
if (!executed) {
executed = true;
// do something
}
};
})();
something(); // "do something" happens
something(); // nothing happens
In answer to a comment by #Vladloffe (now deleted): With a global variable, other code could reset the value of the "executed" flag (whatever name you pick for it). With a closure, other code has no way to do that, either accidentally or deliberately.
As other answers here point out, several libraries (such as Underscore and Ramda) have a little utility function (typically named once()[*]) that accepts a function as an argument and returns another function that calls the supplied function exactly once, regardless of how many times the returned function is called. The returned function also caches the value first returned by the supplied function and returns that on subsequent calls.
However, if you aren't using such a third-party library, but still want a utility function (rather than the nonce solution I offered above), it's easy enough to implement. The nicest version I've seen is this one posted by David Walsh:
function once(fn, context) {
var result;
return function() {
if (fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
I would be inclined to change fn = null; to fn = context = null;. There's no reason for the closure to maintain a reference to context once fn has been called.
Usage:
function something() { /* do something */ }
var one_something = once(something);
one_something(); // "do something" happens
one_something(); // nothing happens
[*] Be aware, though, that other libraries, such as this Drupal extension to jQuery, may have a function named once() that does something quite different.
Replace it with a reusable NOOP (no operation) function.
// this function does nothing
function noop() {};
function foo() {
foo = noop; // swap the functions
// do your thing
}
function bar() {
bar = noop; // swap the functions
// do your thing
}
Point to an empty function once it has been called:
function myFunc(){
myFunc = function(){}; // kill it as soon as it was called
console.log('call once and never again!'); // your stuff here
};
<button onClick=myFunc()>Call myFunc()</button>
Or, like so:
var myFunc = function func(){
if( myFunc.fired ) return;
myFunc.fired = true;
console.log('called once and never again!'); // your stuff here
};
// even if referenced & "renamed"
((refToMyfunc)=>{
setInterval(refToMyfunc, 1000);
})(myFunc)
UnderscoreJs has a function that does that, underscorejs.org/#once
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
Talking about static variables, this is a little bit like closure variant:
var once = function() {
if(once.done) return;
console.log('Doing this once!');
once.done = true;
};
once(); // Logs "Doing this once!"
once(); // Logs nothing
You could then reset a function if you wish:
once.done = false;
once(); // Logs "Doing this once!" again
You could simply have the function "remove itself"
​function Once(){
console.log("run");
Once = undefined;
}
Once(); // run
Once(); // Uncaught TypeError: undefined is not a function
But this may not be the best answer if you don't want to be swallowing errors.
You could also do this:
function Once(){
console.log("run");
Once = function(){};
}
Once(); // run
Once(); // nothing happens
I need it to work like smart pointer, if there no elements from type A it can be executed, if there is one or more A elements the function can't be executed.
function Conditional(){
if (!<no elements from type A>) return;
// do stuff
}
var quit = false;
function something() {
if(quit) {
return;
}
quit = true;
... other code....
}
simple decorator that easy to write when you need
function one(func) {
return function () {
func && func.apply(this, arguments);
func = null;
}
}
using:
var initializer= one( _ =>{
console.log('initializing')
})
initializer() // 'initializing'
initializer() // nop
initializer() // nop
try this
var fun = (function() {
var called = false;
return function() {
if (!called) {
console.log("I called");
called = true;
}
}
})()
From some dude named Crockford... :)
function once(func) {
return function () {
var f = func;
func = null;
return f.apply(
this,
arguments
);
};
}
Reusable invalidate function which works with setInterval:
var myFunc = function (){
if (invalidate(arguments)) return;
console.log('called once and never again!'); // your stuff here
};
const invalidate = function(a) {
var fired = a.callee.fired;
a.callee.fired = true;
return fired;
}
setInterval(myFunc, 1000);
Try it on JSBin: https://jsbin.com/vicipar/edit?js,console
Variation of answer from Bunyk
Here is an example JSFiddle - http://jsfiddle.net/6yL6t/
And the code:
function hashCode(str) {
var hash = 0, i, chr, len;
if (str.length == 0) return hash;
for (i = 0, len = str.length; i < len; i++) {
chr = str.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
var onceHashes = {};
function once(func) {
var unique = hashCode(func.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]);
if (!onceHashes[unique]) {
onceHashes[unique] = true;
func();
}
}
You could do:
for (var i=0; i<10; i++) {
once(function() {
alert(i);
});
}
And it will run only once :)
Initial setup:
var once = function( once_fn ) {
var ret, is_called;
// return new function which is our control function
// to make sure once_fn is only called once:
return function(arg1, arg2, arg3) {
if ( is_called ) return ret;
is_called = true;
// return the result from once_fn and store to so we can return it multiply times:
// you might wanna look at Function.prototype.apply:
ret = once_fn(arg1, arg2, arg3);
return ret;
};
}
If your using Node.js or writing JavaScript with browserify, consider the "once" npm module:
var once = require('once')
function load (file, cb) {
cb = once(cb)
loader.load('file')
loader.once('load', cb)
loader.once('error', cb)
}
If you want to be able to reuse the function in the future then this works well based on ed Hopp's code above (I realize that the original question didn't call for this extra feature!):
var something = (function() {
var executed = false;
return function(value) {
// if an argument is not present then
if(arguments.length == 0) {
if (!executed) {
executed = true;
//Do stuff here only once unless reset
console.log("Hello World!");
}
else return;
} else {
// otherwise allow the function to fire again
executed = value;
return;
}
}
})();
something();//Hello World!
something();
something();
console.log("Reset"); //Reset
something(false);
something();//Hello World!
something();
something();
The output look like:
Hello World!
Reset
Hello World!
A simple example for turning on light only once.
function turnOnLightOnce() {
let lightOn = false;
return function () {
if (!lightOn) {
console.log("Light is not on...Turning it on for first and last time");
lightOn = true;
}
};
}
const lightOn = turnOnLightOnce();
lightOn() // Light is not on...Turning it on for first and last time
lightOn()
lightOn()
lightOn()
lightOn()
https://codesandbox.io/s/javascript-forked-ojo0i?file=/index.js
This happens due to closure in JavaScript.
function once (fn1) {
var ran = false
var memo = null
var fn = function(...args) {
if(ran) {return memo}
ran = true
memo = fn1.apply(null, args)
return memo
}
return fn
}
I'm using typescript with node and it was #I Hate Lazy's answer that inspired me. I just assigned my function to a noop function.
let printName = (name: string) => {
console.log(name)
printName = () => {}
}
printName('Sophia') // Sophia
printName('Nico') // Nothing Happens
https://jsbin.com/yuzicek/edit?js,console
FOR EVENT HANDLER
If the function is a callback for an event listener, there is already a built-in option in the addEventListner method for just executing the callback once.
It can accept 3 parameters
Type
callback
options
options is an object that has a property called once
ex:
const button = document.getElementById('button');
const callbackFunc = () => {
alert('run')
}
button.addEventListener('click', callbackFunc, { once: true })
<button id="button">Click Once</button>
Trying to use underscore "once" function:
var initialize = _.once(createApplication);
initialize();
initialize();
// Application is only created once.
http://underscorejs.org/#once
var init = function() {
console.log("logges only once");
init = false;
};
if(init) { init(); }
/* next time executing init() will cause error because now init is
-equal to false, thus typing init will return false; */
if (!window.doesThisOnce){
function myFunction() {
// do something
window.doesThisOnce = true;
};
};
If you're using Ramda, you can use the function "once".
A quote from the documentation:
once Function
(a… → b) → (a… → b)
PARAMETERS
Added in v0.1.0
Accepts a function fn and returns a function that guards invocation of fn such that fn can only ever be called once, no matter how many times the returned function is invoked. The first value calculated is returned in subsequent invocations.
var addOneOnce = R.once(x => x + 1);
addOneOnce(10); //=> 11
addOneOnce(addOneOnce(50)); //=> 11
keep it as simple as possible
function sree(){
console.log('hey');
window.sree = _=>{};
}
You can see the result
JQuery allows to call the function only once using the method one():
let func = function() {
console.log('Calling just once!');
}
let elem = $('#example');
elem.one('click', func);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p>Function that can be called only once</p>
<button id="example" >JQuery one()</button>
</div>
Implementation using JQuery method on():
let func = function(e) {
console.log('Calling just once!');
$(e.target).off(e.type, func)
}
let elem = $('#example');
elem.on('click', func);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p>Function that can be called only once</p>
<button id="example" >JQuery on()</button>
</div>
Implementation using native JS:
let func = function(e) {
console.log('Calling just once!');
e.target.removeEventListener(e.type, func);
}
let elem = document.getElementById('example');
elem.addEventListener('click', func);
<div>
<p>Functions that can be called only once</p>
<button id="example" >ECMAScript addEventListener</button>
</div>
Tossing my hat in the ring for fun, added advantage of memoizing
const callOnce = (fn, i=0, memo) => () => i++ ? memo : (memo = fn());
// usage
const myExpensiveFunction = () => { return console.log('joe'),5; }
const memoed = callOnce(myExpensiveFunction);
memoed(); //logs "joe", returns 5
memoed(); // returns 5
memoed(); // returns 5
...
You can use IIFE. IIFE means Immediately Invoked Function Expression and the result is to call a function only once by the time is created.
Your code will be like this:
(function () {
//The code you want to execute only one time etc...
console.log("Hello world");
})()
Additionally, this way the data in the function remains encapsulated.
Of course and you can return values from the function and stored them into a new variable, by doing:
const/let value = (function () {
//The code you want to execute only one time etc...
const x = 10;
return x;
})()
function x()
{
let a=0;
return function check()
{
if(!a++)
{
console.log("This Function will execute Once.")
return;
}
console.log("You Can't Execute it For the Second Time.")
return;
}
}
z=x()
z() //Op - This Function will execute once
z() //OP - You can't Execute it for the second time.
I find it useful to just have a simple function that just returns true once, so you can keep the side effects higher up.
let once = () => !! (once = () => false);
once() // true
once() // false
Use like this:
if (once()) {
sideEffect()
}
This exploits the fact that you can coerce an assignment expression to return true while changing the same function into a function that returns false.
If you must have it execute a function, it can be adapted using a ternary:
let once = (x) => !! (once = () => false) ? x() : false;
Now it accepts a single function as an argument. Fun fact, the second false is never reached.
// This is how function in JavaScript can be called only once
let started = false;
if (!started) {
start() { // "do something" }
}
started = true;
}

How can I detect I'm inside an eval() call?

Does there exist a string s such that
(new Function(s))();
and
eval(s);
behave differently? I'm trying to "detect" how a string is being evaluated.
Check for the arguments object. If it exists, you're in the function. If it doesn't it has been evaled.
Note that you'll have to put the check for arguments in a try...catch block like this:
var s = 'try {document.writeln(arguments ? "Function" : "Eval") } catch(e) { document.writeln("Eval!") }';
(new Function(s))();
eval(s);
Demo
Solution to nnnnnn's concern. For this, I've edited the eval function itself:
var _eval = eval;
eval = function (){
// Your custom code here, for when it's eval
_eval.apply(this, arguments);
};
function test(x){
eval("try{ alert(arguments[0]) } catch(e){ alert('Eval detected!'); }");
}
test("In eval, but it wasn't detected");​
The current answer does not work in strict mode since you can't redefine eval. Moreover, redefining eval is problematic for many other reasons.
The way to differenciate them is based on the fact that well... one of them creates a function and what doesn't. What can functions do? They can return stuff :)
We can simply exploit that and do something with return:
// is in function
try {
return true;
} catch(e) { // in JS you can catch syntax errors
false; //eval returns the return of the expression.
}
So in example:
var s = "try{ return true; }catch(e){ false; }";
eval(s); // false
Function(s)(); // true
(new Function(s))(); // true, same as line above
(function(){ return eval(s); })(); // the nested 'problematic' case - false
evaled code can be detected by invoking an error and checking if the native stack-trace contains a lower row/column indicator.
if (typeof window === 'object') {
// browser
window.isEvilEval = function () {
return parseInt(String(new Error().stack).split(':').pop(), 10) < 10;
};
} else {
// nodejs (must be global to be callable from within Function)
global.isEvilEval = function () {
return (
new Error().stack
.split('\n')
.filter((l) => l.trim().startsWith('at eval') && l.indexOf('<anonymous>:1') > -1).length > 0
);
};
}
// test - directly in code => false
console.log(isEvilEval());
// test - in evil eval => true
eval('console.log(isEvilEval())');
// test scoped in function => false
Function('console.log(isEvilEval())')();

How can implement overloading in JavaScript/jQuery?

Im trying to call functions with same signature.
Example: There are two functions with same name:
<script>
var obj1,obj2,obj3,obj4,obj5;
function OpenBox(obj1,obj2){
// code
}
function OpenBox(obj1,obj2,obj3,obj4,obj5){
// code
}
</script>
When I calling function on click event of link
<a id='hlnk1' href='#' onclick='OpenBox(this,\"abhishek\"); return false;'> Open Box </a>
When I click on the above link it is calling function OpenBox(obj1,obj2,obj3,obj4,obj5){}
It should be call function OpenBox(obj1,obj2){} Instead.
What's going wrong in functions?
mattn has the correct idea. Because javascript has no typing those functions are equivalent. What you could do is something like this:
function OpenBox_impl1(obj1,obj2){
// code
}
function OpenBox_impl2(obj1,obj2,obj3,obj4,obj5){
// code
}
function OpenBox(obj1, obj2, obj3, obj4, obj5) {
if(arguments.length == 2)
return OpenBox_impl1(obj1, obj2);
else
return OpenBox_impl2(obj1,obj2,obj3,obj4,obj5);
}
javascript can't define duplicate function in same scope. check arguments.length are 2 or 5.
You cannot overload functions in JavaScript. Instead, the most recently defined version of the function will be used, which is why in your case the version with 5 parameters is called (the final 3 are just undefined).
There are several ways around this, one if which is shown in Mikola's answer. An alternative is to pass in an object, and then check the contents of that object in the function (see this question):
function foo(a, b, opts) {
}
foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});
Another option is to check arguments.length:
function foo(a, b) {
if(arguments.length > 2) {
var arg3 = arguments[3];
//etc...
}
}
in the polymorphism you can use a different signature method ,in javascript we can simulate polymorphism checking the type of the function parameter and execute certain task.
var input = document.getElementById('data');
polymorphism(input);
polymorphism('Hello word 2');
polymorphism('hello word 3', 5);
function polymorphism(arg,arg1){
var string = null;
var sqr = 0;
if(typeof arg === 'string'){
string = 'arg type String: \n'+arg;
}else if (arg.tagName && arg.tagName === 'INPUT'){
string = 'arg type Input: \n'+arg.value;
}
if(arg1 && typeof arg1 === 'number'){
sqr = arg1*arg1;
alert(string + ' and sqr = '+sqr);
}else {
alert(string);
}
}
Check this example in JSFIDDLE
#abshik ,
There is nothing like that which is similar to c# or java. Javasccript behaves this way
function Test(arg1 ,arg2 , arg3, arg4)
{
}
when you are calling this function you can call in the following ways
Test(arg1);
Test(arg1,arg2);
Test(arg1,arg2,arg3);
Test(arg1,arg2,arg3,arg4);
But sequence matters , so you can the function in the above ways.
The issue is that you are trying to overload a function but that is not supported by Javascript. I think your best option is to use Polymorphism instead. View this article for more details: http://www.cyberminds.co.uk/blog/articles/polymorphism-in-javascript.aspx
Once a function is defined in ecmascript, that name is locked. However, you can pass any number of parameters to that function so you do the rest of the work on the inside.
function foo(arg1, arg2) {
// any code that is needed regardless of param count
if(arg2 !== undefined) {
// run function with both arguments
console.log(arguments);
} else if(arg1 !== undefined) {
// run function with one argument
} else {
// run function with no arguments
}
}
foo(1);
foo(1,2);
foo(1,2,3);
Interesting note: you can pass in extra parameters that aren't in the function declaration. Do a console.log of arguments and you'll see everything in there. arguments is an object which can be accessed like / typecasted to an array.

Wrapping a function in Javascript / jQuery

If I have an arbitrary function myFunc, what I'm aiming to do is replace this function with a wrapped call that runs code before and after it executes, e.g.
// note: psuedo-javascript
var beforeExecute = function() { ... }
var afterExecute = function() { ... }
myFunc = wrap(myFunc, beforeExecute, afterExecute);
However, I don't have an implementation of the required wrap function. Is there anything that already exists in jQuery like this (I've had a good look through the docs but cannot see anything)? Alternatively does anybody know of a good implementation of this because I suspect that there are a bunch of edge cases that I'll miss if I try to write it myself?
(BTW - the reason for this is to do some automatic instrumentation of functions because we do a lot of work on closed devices where Javascript profilers etc. are not available. If there's a better way than this then I'd appreciate answers along those lines too.)
Here’s a wrap function which will call the before and after functions with the exact same arguments and, if supplied, the same value for this:
var wrap = function (functionToWrap, before, after, thisObject) {
return function () {
var args = Array.prototype.slice.call(arguments),
result;
if (before) before.apply(thisObject || this, args);
result = functionToWrap.apply(thisObject || this, args);
if (after) after.apply(thisObject || this, args);
return result;
};
};
myFunc = wrap(myFunc, beforeExecute, afterExecute);
The accepted implementation does not provide an option to call wrapped (original) function conditionally.
Here is a better way to wrap and unwrap a method:
/*
Replaces sMethodName method of oContext with a function which calls the wrapper
with it's list of parameters prepended by a reference to wrapped (original) function.
This provides convenience of allowing conditional calls of the
original function within the wrapper,
unlike a common implementation that supplies "before" and "after"
cross cutting concerns as two separate methods.
wrap() stores a reference to original (unwrapped) function for
subsequent unwrap() calls.
Example:
=========================================
var o = {
test: function(sText) { return sText; }
}
wrap('test', o, function(fOriginal, sText) {
return 'before ' + fOriginal(sText) + ' after';
});
o.test('mytext') // returns: "before mytext after"
unwrap('test', o);
o.test('mytext') // returns: "mytext"
=========================================
*/
function wrap(sMethodName, oContext, fWrapper, oWrapperContext) {
var fOriginal = oContext[sMethodName];
oContext[sMethodName] = function () {
var a = Array.prototype.slice.call(arguments);
a.unshift(fOriginal.bind(oContext));
return fWrapper.apply(oWrapperContext || oContext, a);
};
oContext[sMethodName].unwrapped = fOriginal;
};
/*
Reverts method sMethodName of oContext to reference original function,
the way it was before wrap() call
*/
function unwrap(sMethodName, oContext) {
if (typeof oContext[sMethodName] == 'function') {
oContext[sMethodName] = oContext[sMethodName].unwrapped;
}
};
This is the example I would use
<script type="text/javascript">
var before = function(){alert("before")};
var after = function(param){alert(param)};
var wrap = function(func, wrap_before, wrap_after){
wrap_before.call();
func.call();
wrap_after.call();
};
wrap(function(){alert("in the middle");},before,function(){after("after")});
</script>
You could do something like:
var wrap = function(func, pre, post)
{
return function()
{
var callee = arguments.callee;
var args = arguments;
pre();
func.apply(callee, args);
post();
};
};
This would allow you to do:
var someFunc = function(arg1, arg2)
{
console.log(arg1);
console.log(arg2);
};
someFunc = wrap(
someFunc,
function() { console.log("pre"); },
function() { console.log("post"); });
someFunc("Hello", 27);
Which gives me an output in Firebug of:
pre
Hello
27
post
The important part when wrapping this way, is passing your arguments from the new function back to the original function.
Maybe I'm wrong, but I think you can directly create an anonym function and assign it to myFunc:
myFunc = function(){
BeforeFunction();
myFunc();
AfterFunction();
}
In this way you can control the arguments of every function.

Categories