Different output in 3 anonymous function in GAS - javascript

I have a question.
In the formal web page of google.script run, they saids that you can call "any server-side function" from client side using google.script.run.
In the below gs file, I defined function "hoge" using normal function expression.(the "this!" row)
If I execute this situation, output is randomly 1-4 numbers displayed on browser
By the way, I tried to change the define style of function "hoge". I created 3 pattern using anonymous function. (all are called from client side using "hoge(vv)")
var hoge = function hoge(x){return x;}; (both side using "hoge" keyword) → then this worked same as normal function definition style.
var hoge = function (x){return x;}; (only left using "hoge" keyword) → error
var hogeNot = function hoge(x){return x;}; (only right using "hoge" keyword) → error
Q. Why, "1" work well, but "2" is error.
Thank you.
// gs file
var x;
function doGet() {
return HtmlService.createTemplateFromFile("hello").evaluate(); // テンプレートオブジェクトの取得
}
function hoge(x){ // this!
return x;
}
// html file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p id="wi">hello</p>
<script>
function success(get){
document.getElementById("wi").insertAdjacentHTML("afterend","<p>" + get + "</p>");
}
for (var v=1; v <= 4; ++v){ // aaを4回呼ぶ
aa(v);
}
async function aa(vv){
await google.script.run.withSuccessHandler(success).hoge(vv);
}
</script>
</body>
</html>

Q. Why, "1" work well, but "2" is error.
For this question, how about this answer? Please think of this as just one of several possible answers.
Experiment:
At Google Apps Script, it seems that when the function can be recognized with the script editor and the function can be seen at this, the function can be directly run. For checking whether the function is included in this, the following script can be used.
Sample script:
function myFunction() {
for (var i in this) {
if (i == "hoge") {
Logger.log("%s, %s", i, typeof this[i])
}
}
}
About var hoge = function hoge(x){return x;};
In this case, the function of hoge can be seen at the script editor and this function can be directly run by the script editor. And also, above script returns hoge, function.
About var hoge = function (x){return x;};
In this case, the function of hoge cannot be seen at the script editor while above script returns hoge, function. And hoge cannot be directly run because this cannot be seen at the script editor.
When this function of hoge is run from other function, the script works.
About var hogeNot = function hoge(x){return x;};
In this case, the function of hogeNot cannot be seen at the script editor. But the function of hoge can be seen at the script editor. When the function of hoge is run by the script editor, an error like the function is not found occurs. At the above script, i == "hoge" is always false. But when i == "hogeNot" is used for the if statement, hogeNot, function is returned.
When this function of hogeNot is run from other function, the script works. But when this function of hoge is run from other function, an error occurs.
Result:
From above situations, it is considered that in order to run with google.script.run, it is required to be able to directly run the function at the script editor. I think that this might be the specification of Google side.
If I misunderstood your question and this was not the direction you want, I apologize.

Related

How do I prevent execution of a certain line of Javascript code? [duplicate]

This question already has answers here:
Stop execution of Javascript function (client side) or tweak it
(5 answers)
Closed 1 year ago.
Let's imagine you are visiting a website that utilizes JavaScript (jquery). Of course, there are some function definitions in the script. Like this one:
$(function () {
// Some necessary code here...
someObject.doSomethingUndesirable();
// Some necessary code here...
});
My problem is that I do not want that line of code to be executed. Of course I can comment out that particular line after the page is loaded, but since the script is already in memory, the modification will not work.
So my question is simple: Can I somehow interfere with the loading process and prevent the loading (and therefore execution) of a particular line of JavaScript code?
If you can inject code before the site code runs - such as with a userscript and the #run-at document-start directive - you can overwrite $ to ignore the callback:
// Userscript code
$ = (callback) => {};
// Site code
$(function() {
someObject.doSomethingUndesirable();
});
If $ may not be defined yet, you can also define a setter on window.$, so that its initial assignment gets ignored or overwritten:
// Userscript code
Object.defineProperty(window, '$', {
get() {
return (callback) => {};
}
});
// Site code
$(function() {
someObject.doSomethingUndesirable();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Tricker but more flexible approaches are to detect the appending of the site's <script> node and patch it, or to patch it in advance with Chrome Local Overrides or a network tool like Fiddler.
I guess you could use userscript to modify the class of the object if it's static. One way to do this is to listen on changes over the 'someObject' variable via the Proxy object. Then whenever he defines the doSomethingUndesirable function you could just replace it with a function that returns nothing, null or whatever you want.
//Init variable
var someObject = {};
var someObjectProxy = new Proxy(someObject, {
set: function (target, key, value) {
if(key = "doSomethingUndesirable"){
//Redefinition of the function
target[key] = ()=>{return null};}
return true;
}
});
/*....*/
//Example of definition
someObject.somethingUndesirable = ()=>{return 10+10}
//The proxy will trigger and redefine the function to return null

Sourcing Global Function from an Anonymous Function that Returns in Adobe DTM

The below code snippets are not the actual code, they are only there to explain my issue. So please don't concentrate on the actual functionality. I'm working with Adobe DTM. I have no idea how to get an anonymous function that returns a value (as a Data Element to source a global function? If I have a normal anonymous function within my data Element, everything works fine. If the anonymous function returns, then it doesn't work? Is there any way to get this to work? Example:
//global function
function _myGlobalFunct(str){
return (str);
}
the following code of an anonymous function within the Data Element calls global function and it works as expected:
// working anonymous function
(function () {
window._myGlobalFunct("value1");
})()
but the following return anonymous function, within the Data Element, doesn't call my function but doesn't throw any errors? :
// Not Working Properly but doesn't throw any errors?
return (function() {
var rvalue = document.title || "No Title";
window._myGlobalFunct(rvalue);
return rvalue;
})();
I do know the function is executing but not getting any errors in Chrome?
DTM's data elements execute the code provided within a function (that may not be clear to the other users here), so there will be a return outside of a function in the code you input/show here. You're not returning the value from your function (or if you're trying to update rvalue within the function and rvalue isn't in the right scope (window vs. local)). In any case, is there a reason you're using the anonymous function anyways? Below should work:
var rvalue = document.title || "No Title";
return window._myGlobalFunct(rvalue);
If you still want the anonymous function, make sure to grab the return value from your function:
return (function() {
var rvalue = document.title || "No Title";
return window._myGlobalFunct(rvalue);
})();
I don't think you can return a self-invoking function and then return again in the function.
Since I can't comment yet I will explain it here in more detail, why it is indeed a duplicate. The first answer by Niet the Dark Absol in the link I mentioned above(for reference: Syntax error: Illegal return statement in JavaScript), clearly says the following:
return only makes sense inside a function. There is no function in
your code.
To apply this to your case:
return (function() {
Is your first line, if you would encapsulate everything in another function and call that one everything will be working fine, e.g.:
function myFunction(){
return (function() {
var rvalue = document.title || "No Title";
window._myGlobalFunct(rvalue);
return rvalue;
})();
}
And then you can call myFunction() to get your return value. I hope this helps you out.

Differences when using functions for casper.evaluate

I'm using PhantomJS v2.0 and CasperJS 1.1.0-beta3. I want to query a specific part inside the page DOM.
Here the code that did not work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc());
this.echo("value: " + del);
And here the code that did work:
var del=this.evaluate(function()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
});
this.echo("value: " + del);
It seems to be the same, but it works different, I don't understand.
And here a code that did also work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc);
this.echo("value: " + del);
The difference here, I call the myfunc without the '()'.
Can anyone explain the reason?
The problem is this:
var text = this.evaluate(myfunc());
Functions in JavaScript are first class citizen. You can pass them into other functions. But that's not what you are doing here. You call the function and pass the result into evaluate, but the result is not a function.
Also casper.evaluate() is the page context, and only the page context has access to the document. When you call the function (with ()) essentially before executing casper.evaluate(), you erroneously try to access the document, when it is not possible.
The difference to casper.evaluate(function(){...}); is that the anonymous function is defined and passed into the evaluate() function.
There are cases where a function should be called instead of passed. For example when currying is done, but this is not applicable to casper.evaluate(), because it is sandboxed and the function that is finally run in casper.evaluate() cannot use variables from outside. It must be self contained. So the following code will also not work:
function myFunc2(a){
return function(){
// a is from outer scope so it will be inaccessible in `evaluate`
return a;
};
}
casper.echo(casper.evaluate(myFunc2("asd"))); // null
You should use
var text = this.evaluate(myfunc);
to pass a previously defined function to run in the page context.
It's also not a good idea to use reserved keywords like del as variable names.

Why is this function being called?

I am trying to modify some behavior of a framework's JavaScript. In IE10's developer tools under the View source drop down, there is a folder called Dynamic Scripts. (Maybe someone could explain what Dynamic Scripts are?) And there is the following code under Function code (1089)
This is the code:
function anonymous() {
var f=arguments.callee; return f._func.apply(f._owner, arguments);
}
And the first entry of the call stack is
Function code, Function code (1089), line 2
This line gets executed several times. But I don't know why.
Who calls this line?
The anonymous function call does not mean a function called anonymous. It is actually a name that is used to classify unnamed functions, like this one:
var anUnnamedFunc = function() {
return true;
};
If you referenced this function in a watch or console output, it would be dumped as an anonymous function. To define a function that isn't anonymous, you would use:
var aNamedFunc = function namedFunction() {
return true;
};
The function being called in question, looks a lot like a bind function. That is a wrapper function used to create a function that binds arguments and or context to another function. However, this version uses some sort of private property mechanism to bind arguments:
var bind = function() {
var f = arguments.callee;
return f._func.apply(f._owner, arguments);
};
I actually don't see what this sort of function would be used for, so wonder if it is just an anomaly of the IE debugger. Try using a different browser and see if that function appears in the profile report.

Strange behavior on function calling

When calling a Javascript function, it seems like JS gives priority to functions without parameters first, even if I have the same function name with parameters.
The strange behavior only happens in the following scenario:
I have a an HTML page with embedded Javascript, like this:
//Javascript in the page
function testAbc(){
alert('testAbc no params');
}
//Javascript in common.js
function testAbc(x){
alert('testAbc with param:'+x);
}
function testAbcFunc(x){
testAbc(x);
}
Now from somewhere in the page, im calling testAbcFunc from the common.js expecting it to call testAbc with parameter which is the common function. But strangely, JS calls back the function in the original page without params!!
I have been debugging this bug fore few hours now, and i tried this short code to reproduce the bug, it does happen each time.
NOTE: if all functions are in the same page, the correct function (with params) will be called, but when ther are split between the page and the JS file. JS seems to give priority to the function in the page even though is doesn't have parameter
JavaScript does not support method overloading based on parameters. It simply uses the last-defined function if multiple functions have the same name. The version in the page will override the included version. When it worked for you, I assume that the include version (with the argument signature) was inlined after the original.
JavaScript doesn't have overloaded function. It doesn't care about signatures, it calls functions solely by names and nothing else. It is strange that later function does not completely hide the first one but well, there's no spec about that behaviour.
So just don't do that, check the number of params with arguments.length inside the function and don't try to use overloading which will never work.
function testAbc(){
if (arguments.length == 0) {
alert('testAbc no params');
} else {
var x = arguments[0];
alert('testAbc with param:'+x);
}
}
There is no function overloading in JavaScript. If you are defining a function with two times with diffrent number of parameters the last one to be defined will be called.
Also, you should be namespacing your JavaScript.
Like so:
var common = {
testABC: function () {
//Stuff
}
};
Then call testABC like this
common.testABC();

Categories