I'm new to ES6 Javascript which means i'm exploring it. I like the arrow function and default parameter feature from ES6 which is mentioned in the below site.
http://es6-features.org/#ExpressionBodies
http://es6-features.org/#DefaultParameterValues
Below is my code snippet of ES6 and i have tested this in Chrome 47. I'm trying to give default parameter value for my arrow function which is currently throwing error like
<script type="text/javascript">
'use strict';
var greet = (name = 'Venkat') => (console.log('Hi ' + name + '!'));
greet(); // expected output: Venkat
greet('Venkatraman'); // expected output: Venkatraman
</script>
Let me know whether its possible, if so, explain with solution and what i'm doing wrong here.
No, that's not possible (yet, I suppose). What you can do though:
var greet = name => console.log('Hi ' + (name || 'Venkat') + '!');
greet(); // output: Venkat
greet('Venkatraman'); // output: Venkatraman
Try it here
[jan 2018] The default parameter value is now supported in all major browsers I suppose
It seems it support only in Firefox
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
Related
Here a simple code i'm trying to run in google sheets script.
The purpose is supplying the foreach callback function additional parameters.
function print(str, num) {
Logger.log(str + ": " + num);
}
function test()
{
var array = [1,2,3];
var str = "Stam";
//This line has an exception
// TypeError: Cannot convert null to an object
array.forEach(print.bind(null, str));
}
test();
this code is based on the solution described here.
I know there are other solutions, though i want to understand why this one does not work.
I wounder maybe it is not supported with google sheets.
How about this answer? Please think of this as just one of several possible answers.
At Javascript, when null of bind(null, str) is used, this is used. At Google Apps Script, when null is used for bind(null, str), an error occurs like "Cannot convert null to an object". I think that this might be the specification of Google side. I'm not sure whether this is modified in the future update. So as the current workaround, how about using this instead of null? Or if you want to use bind(null, str) like null under the strict mode, how about using {} instead of null like bind({}, str)?
By the way, I think that test(); at the last line of your script can be removed. Because in your case, when test() is run at the script editor, test() is run 2 times by test(); at the last line. test(); at the last line is run as the global.
From above situation, when your script is modified, how about the following modification?
Modified script:
function print(str, num) {
Logger.log(str + ": " + num);
}
function test() {
var array = [1,2,3];
var str = "Stam";
array.forEach(print.bind(this, str));
}
or you can also modify test() of your script as follows. The following test() retrieves the same result with above one.
function test() {
var array = [1,2,3];
var str = "Stam";
array.forEach(function(e) {print(str, e)});
}
Result:
When you run test() at the script editor, you can see the following result at the log.
Stam: 1
Stam: 2
Stam: 3
Reference:
Function.prototype.bind()
If I misunderstood your question and this was not the direction you want, I apologize.
I am getting this error in chrome while mozilla is handling good. I am getting this error to a function which is like this
function abc( xyz = false){ "My logic" }
Error is pointing to '=' operator. please help with this.
That is a standard of ECMASCRIPT version 6 and it's called Default parameters. So it might be not available in your chrome version while FF has.
You can achieve the same by two ways:
function abc( xyz ){ "My logic" }
var pVal = mightbe || false;
abc(pVal); //<---- now pass it here;
or:
function abc( xyz ){
// before processing anything you can do this
var o = xyz || false; // if there is any value in the xyz then that will
// be assigned otherwise false will be the default value.
"My logic"
}
This is ES6 syntax, most browsers only support very few ES6 features, you can check from here: https://kangax.github.io/compat-table/es6/ (In your example you used default function parameters)
If you want to write ES6 syntax (which is quite appealing in many ways), you can use some code transpiling tool like babel: https://babeljs.io/
In Ruby I think you can call a method that hasn't been defined and yet capture the name of the method called and do processing of this method at runtime.
Can Javascript do the same kind of thing ?
method_missing does not fit well with JavaScript for the same reason it does not exist in Python: in both languages, methods are just attributes that happen to be functions; and objects often have public attributes that are not callable. Contrast with Ruby, where the public interface of an object is 100% methods.
What is needed in JavaScript is a hook to catch access to missing attributes, whether they are methods or not. Python has it: see the __getattr__ special method.
The __noSuchMethod__ proposal by Mozilla introduced yet another inconsistency in a language riddled with them.
The way forward for JavaScript is the Proxy mechanism (also in ECMAscript Harmony), which is closer to the Python protocol for customizing attribute access than to Ruby's method_missing.
The ruby feature that you are explaining is called "method_missing" http://rubylearning.com/satishtalim/ruby_method_missing.htm.
It's a brand new feature that is present only in some browsers like Firefox (in the spider monkey Javascript engine). In SpiderMonkey it's called "__noSuchMethod__" https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/NoSuchMethod
Please read this article from Yehuda Katz http://yehudakatz.com/2008/08/18/method_missing-in-javascript/ for more details about the upcoming implementation.
Not at the moment, no. There is a proposal for ECMAScript Harmony, called proxies, which implements a similar (actually, much more powerful) feature, but ECMAScript Harmony isn't out yet and probably won't be for a couple of years.
You can use the Proxy class.
var myObj = {
someAttr: 'foo'
};
var p = new Proxy(myObj, {
get: function (target, methodOrAttributeName) {
// target is the first argument passed into new Proxy, aka. target is myObj
// First give the target a chance to handle it
if (Object.keys(target).indexOf(methodOrAttributeName) !== -1) {
return target[methodOrAttributeName];
}
// If the target did not have the method/attribute return whatever we want
// Explicitly handle certain cases
if (methodOrAttributeName === 'specialPants') {
return 'trousers';
}
// return our generic method_missing function
return function () {
// Use the special "arguments" object to access a variable number arguments
return 'For show, myObj.someAttr="' + target.someAttr + '" and "'
+ methodOrAttributeName + '" called with: ['
+ Array.prototype.slice.call(arguments).join(',') + ']';
}
}
});
console.log(p.specialPants);
// outputs: trousers
console.log(p.unknownMethod('hi', 'bye', 'ok'));
// outputs:
// For show, myObj.someAttr="foo" and "unknownMethod" called with: [hi,bye,ok]
About
You would use p in place of myObj.
You should be careful with get because it intercepts all attribute requests of p. So, p.specialPants() would result in an error because specialPants returns a string and not a function.
What's really going on with unknownMethod is equivalent to the following:
var unk = p.unkownMethod;
unk('hi', 'bye', 'ok');
This works because functions are objects in javascript.
Bonus
If you know the number of arguments you expect, you can declare them as normal in the returned function.
eg:
...
get: function (target, name) {
return function(expectedArg1, expectedArg2) {
...
I've created a library for javascript that let you use method_missing in javascript: https://github.com/ramadis/unmiss
It uses ES6 Proxies to work. Here is an example using ES6 Class inheritance. However you can also use decorators to achieve the same results.
import { MethodMissingClass } from 'unmiss'
class Example extends MethodMissingClass {
methodMissing(name, ...args) {
console.log(`Method ${name} was called with arguments: ${args.join(' ')}`);
}
}
const instance = new Example;
instance.what('is', 'this');
> Method what was called with arguments: is this
No, there is no metaprogramming capability in javascript directly analogous to ruby's method_missing hook. The interpreter simply raises an Error which the calling code can catch but cannot be detected by the object being accessed. There are some answers here about defining functions at run time, but that's not the same thing. You can do lots of metaprogramming, changing specific instances of objects, defining functions, doing functional things like memoizing and decorators. But there's no dynamic metaprogramming of missing functions as there is in ruby or python.
I came to this question because I was looking for a way to fall through to another object if the method wasn't present on the first object. It's not quite as flexible as what your asking - for instance if a method is missing from both then it will fail.
I was thinking of doing this for a little library I've got that helps configure extjs objects in a way that also makes them more testable. I had seperate calls to actually get hold of the objects for interaction and thought this might be a nice way of sticking those calls together by effectively returning an augmented type
I can think of two ways of doing this:
Prototypes
You can do this using prototypes - as stuff falls through to the prototype if it isn't on the actual object. It seems like this wouldn't work if the set of functions you want drop through to use the this keyword - obviously your object wont know or care about stuff that the other one knows about.
If its all your own code and you aren't using this and constructors ... which is a good idea for lots of reasons then you can do it like this:
var makeHorse = function () {
var neigh = "neigh";
return {
doTheNoise: function () {
return neigh + " is all im saying"
},
setNeigh: function (newNoise) {
neigh = newNoise;
}
}
};
var createSomething = function (fallThrough) {
var constructor = function () {};
constructor.prototype = fallThrough;
var instance = new constructor();
instance.someMethod = function () {
console.log("aaaaa");
};
instance.callTheOther = function () {
var theNoise = instance.doTheNoise();
console.log(theNoise);
};
return instance;
};
var firstHorse = makeHorse();
var secondHorse = makeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
This doesn't work for my use case as the extjs guys have not only mistakenly used 'this' they've also built a whole crazy classical inheritance type system on the principal of using prototypes and 'this'.
This is actually the first time I've used prototypes/constructors and I was slightly baffled that you can't just set the prototype - you also have to use a constructor. There is a magic field in objects (at least in firefox) call __proto which is basically the real prototype. it seems the actual prototype field is only used at construction time... how confusing!
Copying methods
This method is probably more expensive but seems more elegant to me and will also work on code that is using this (eg so you can use it to wrap library objects). It will also work on stuff written using the functional/closure style aswell - I've just illustrated it with this/constructors to show it works with stuff like that.
Here's the mods:
//this is now a constructor
var MakeHorse = function () {
this.neigh = "neigh";
};
MakeHorse.prototype.doTheNoise = function () {
return this.neigh + " is all im saying"
};
MakeHorse.prototype.setNeigh = function (newNoise) {
this.neigh = newNoise;
};
var createSomething = function (fallThrough) {
var instance = {
someMethod : function () {
console.log("aaaaa");
},
callTheOther : function () {
//note this has had to change to directly call the fallThrough object
var theNoise = fallThrough.doTheNoise();
console.log(theNoise);
}
};
//copy stuff over but not if it already exists
for (var propertyName in fallThrough)
if (!instance.hasOwnProperty(propertyName))
instance[propertyName] = fallThrough[propertyName];
return instance;
};
var firstHorse = new MakeHorse();
var secondHorse = new MakeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
I was actually anticipating having to use bind in there somewhere but it appears not to be necessary.
Not to my knowledge, but you can simulate it by initializing the function to null at first and then replacing the implementation later.
var foo = null;
var bar = function() { alert(foo()); } // Appear to use foo before definition
// ...
foo = function() { return "ABC"; } /* Define the function */
bar(); /* Alert box pops up with "ABC" */
This trick is similar to a C# trick for implementing recursive lambdas, as described here.
The only downside is that if you do use foo before it's defined, you'll get an error for trying to call null as though it were a function, rather than a more descriptive error message. But you would expect to get some error message for using a function before it's defined.
I am working in JavaScript. I want to parse and evaluate conditional expression.
ex:
var param1=1;
var param2=2;
var param3=3;
var expression="(param1==param2)||(param3<param1)";
I want to write a function which will accept 'expression' as a input and parse the expression as well as evaluate expression and return evaluated result.
Please let me know for any suggestions.
Thanks in advance.
Here is the evil one: eval();
var param1=1;
var param2=2;
var param3=3;
var expression=eval("(param1==param2)||(param3<param1)");
Then your function comes,
function myEvaluator(s) {
return eval(s);
}
You must have variables in expression public.
This is a really old question and I am surprised that no libraries came out since to help with this.
Out of necessity, I built a library called angel-eval that does exactly that. It parses a string expression and evaluates with a context object. It uses a parser generator called Nearley under the hood and does not use eval or new Function(…).
To use, install: npm i angel-eval
const { evaluate } = require("angel-eval");
evaluate("(param1===param2)||(param3<param1)", { param1: 1, param2: 2, param3: 3 });
angel-eval does not support == or != so you need to use === and !==.
Here is a sandbox:
There are a few expression parsers out there, but I would like to suggest mine. It's called swan-js and it doesn't use eval or new Function.
Installation:
npm install #onlabsorg/swan-js
Usage (it works both in NodeJS and in the browser):
const swan = require('#onlabsorg/swan-js');
const evaluate = swan.parse("param1 == param2 | param3 < param1");
const context = swan.createContext({param1:1, param2:2, param3:3});
const value = await evaluate(context); // false
I am setting an object like this
n.name = n.name.join(String.fromCharCode(255));
n.description = n.description.join(String.fromCharCode(255));
I want to be able to alert(n); but it tells me [Object]
is there a way to alert complete object?
thanks
Javascript supports adding a toString() function to your objects. This will get called when you alert your object. For example:
n.toString = function(){
return this.name + '\n' + this.description;
}
then alert(n); will display whatever content your function specifies.
I was asking the same kind of question as Autolycus today. I'm using jqGrid and I wanted to see what the object it created actually was. I didn't create the object and I wanted to see what it looked like. I know it's probably old school, but I still use alerts in javascript for some of my debugging (though I agree FireFox & Firebug are the way to go for most things).
I found an answer to what I was looking for here: http://javascript.internet.com/debug-guide.html, which is unbelievably old.
But I tweaked it to give me what I needed and since I think it answers Autolycus's question in a new way and I think someone else might be looking here, like me, for this someday, here it is:
obj = n;
var temp = "";
for (x in obj) {
temp += x + ": " + obj[x] + "\n";
}
alert (temp);
I apologize in advance if answering an old question is breaking some kind of rule.
all best,
ember
I like the var_dump in php, so I often use a function like this to dump variables
function var_dump(object, returnString)
{
var returning = '';
for(var element in object)
{
var elem = object[element];
if(typeof elem == 'object')
{
elem = var_dump(object[element], true);
}
returning += element + ': ' + elem + '\n';
}
if(returning == '')
{
returning = 'Empty object';
}
if(returnString === true)
{
return returning;
}
alert(returning);
}
There are a couple of alternatives:
1. Use http://www.gscottolson.com/blackbirdjs/
2. Use console.log() that comes with Firebug, but requires Firefox (even if you only target only IEs, it's still wise to use Firefox and Firebug as aprt of testing of your web app development)
It depends what you mean by alerting the complete object.
You can't really just output every object as a string and have it make sense. To define how an object will display itself as a string we use the .toString(); method.
So try alert(n.toString()); and see if that will give you what you want. If the object is your own, then define the toString(); and have it return a string of the parameters and fields that you want to output.
Something like...
alert(n.name);
...I think is what you want.
If you are trying to debug, you would be better suited to using FireFox/Firebug instead of inserting a load of alerts();