I am working through the exercises in the book Object-Oriented JavaScript by Stoyan Stefanov. The exercise is asking me to create a function constructor for a String object. None of the built-in String properties or methods can be used. I am trying to recreate returning a character at a certain index of a string. So the following code is the part of the exercise I am having difficulty getting to work:
var s = new MyString('hello');
s[0];
I cannot figure out how to have my function constructor return the character at the index specified. I should be able to display to the screen the character 'h'. I was able to specifically target certain indexes but that would not be usable as there could be any number of characters in the string passed into the function constructor. Here is the code for that, this return value is for the constructor itself:
return {
'0': this.string[0]; // Is this code using built-in String object properties or methods?
}
Okay thanks if you can point me in the right direction.
A simple way to achieve this is to not make it act like a real string, but only deal with the letters that do exist by running over the input string as an array using forEach:
var MyString = function(content) {
var thisObject = this;
var letters = content.split('');
letters.forEach(function(letter, position) {
thisObject[position] = letter;
});
};
JS objects are all dynamic property/value maps, so you can set a binding that is effectively this[0] = 't'; this[1] = 'h'; this[2] = 'e' and have something that works.
Does this make sense to do? Not... really? I don't quite see what this exercise teaches you if it's telling you that your code should allow for yourstring[somenumber], but this would be one way to do it.
Related
How can I create a new function from a string when the string contains if condition?
The string will comes from outside but in the dummy example below everything is hardcoded to be easier.
let f1: number = 1;
let f2: number = 0;
let condition: string = 'if(this.f1===1){this.f2 = 1}';
let result = this.createFn(condition);
createFn(param: string) {
return new Function('return ' + param)();
// or return new Function(param)();
}
Of course this is not working and I'm searching a way to do it.
I don't want to use eval().
Passing a string to the constructor of Function is almost the same as using eval().
To safely execute arbitrary code in JavaScript you need to have a JavaScript interpreter written in JavaScript which will then execute the received string in a sandbox environment. A quick google search yields this package: https://github.com/NeilFraser/JS-Interpreter.
Others who faced this issue have decided to implement themselves a domain-specific subset of a programming language to then allow the strings to execute that language's code. e.g. SAP's SAPUI5/OpenUI5 solution for the Expression Binding they have.
I have a function:
function hello(param){ console.log('param is '+param); }
And two calls. First:
hello(123)
Second:
var a=123; hello(a);
Is there any possible way to tell, from within the hello function, whether param was passed as a var or as a literal value?
NOTICE: I am not trying to solve a problem by this. There are many workarounds of course, I merely wanted to create a nice looking logging function. And also wanted to learn the boundaries of JavaScript. I had this idea, because in JavaScript we have strange and unexpected features, like the ability to obtain function parameter names by calling: function.toString and parsing the text that is returned.
No, primitives like numbers are passed by value in Javascript. The value is copied over for the function, and has no ties to the original.
Edit: How about using an object wrapper to achieve something like this? I'm not sure what you are trying to do exactly.
You could define an array containing objects that you want to keep track of, and check if its in there:
var registry = [] // empty registry
function declareThing(thing){
var arg = { value: thing } // wrap parameter in an object
registry.push(arg) // register object
return arg; //return obj
}
function isRegistered(thingObj){
return (registry.indexOf(thingObj) > -1)
}
var a = declareThing(123);
hello(a);
function hello(param){
console.log(isRegistered(param));
}
Is it possible to keep an object reference without using an holder object in javascript?
Currently when an object gets overridden I sometimes lose the reference to the "current" object state illustrated in the snippet below;
Is there a way to put a "pointer" in an array or not?
EDIT
To the questions asked:
What I have in the objects I have are references to form fields. Some of these are text fields, some of them are textareas, some of them checkboxes.
I wish to keep a map next to the direct referene of what type they are.
basicaly it would be
obj {
this.text1 = createTextField();
this.text1.datepicker();
this.text2 = createTextField();
this.area1 = createArea();
this.check = createCheck();
this.datefields = [this.text1];
this.checkboxes = [this.check];
}
So I can use the datefields/checkboxes array as a checkpoint to validate against which type a field is/should behave.
Currently I use
function datefields() { return [this.text1]; };
But I'd like to know if there's a better way to do this than to intantiate a new array when I need to check it.
I know there is a way with observers to mimic pointer behaviour, and i've fiddled with those and have some good results with that, i'm just curious if there are other ways i'm not aware of.
function myObject() {
this.myvalue = null;
this.arr = [this.myvalue];
}
myObject.prototype.alter = function() {
this.myvalue = "hello";
}
var x = new myObject();
var elem = document.getElementById('results');
function log(message) {
elem.appendChild(document.createTextNode(message));
elem.appendChild(document.createElement('br'));
}
log("x.myvalue = "+x.myvalue);
log("x.arr[0] = "+x.arr[0]);
log("calling alter");
x.alter();
log("x.myvalue = "+x.myvalue);
log("x.arr[0] = "+x.arr[0]);
<div id="results"></div>
Simple answer: Only objects (including all subtypes) are passed by reference in JS. All other simple values are copied.
For a bit more detail I would recommend reading You Don't Know JS: Types & Grammer but specifically the section Value vs Reference in Chapter 2:
In JavaScript, there are no pointers, and references work a bit differently. You cannot have a reference from one JS variable to another variable. That's just not possible.
Quoting further on:
Simple values (aka scalar primitives) are always assigned/passed by value-copy: null, undefined, string, number, boolean, and ES6's symbol.
Compound values -- objects (including arrays, and all boxed object wrappers -- see Chapter 3) and functions -- always create a copy of the reference on assignment or passing.
There are plenty of examples included to show these points. I would highly recommend reading through to get a better understanding of how values/references work in JS.
There is no pointers in Javascript, though you could cheat a little using a wrapper object. Here is a minimal implementation of such an object:
var Wrapper = function (value) {
this.value = value;
};
Wrapper.prototype.valueOf = function () {
return this.value;
};
Then you may use it in place of the original value:
function myObject() {
this.myvalue = new Wrapper(null); // wrapper
this.arr = [this.myvalue];
}
myObject.prototype.alter = function() {
this.myvalue.value = "hello"; // notice the ".value"
}
The rest of your code needs no tweaks.
I come from a Java background, where everything is Object Oriented. While Getting into a bit more of Javascript (more into the class areas of javascript), I've noticed complete changes. The biggest for me is getting used to the prototyping of the so-called "classes" javascript has. So, my question is if you need to intialize the varialbes you pass into your class function constructor method-thing. For example:
function Foo(a, b, c) {
this.a = a;
var b = b;
this.c = "";
this.d = a + b;
}
Now In javascript is this necessary? Cause in Java, you have to show that the variable type definition in the argument itself: Foo(int a, int b, string c) Now how does the method in Javascript know what type of data structure it is being passed too? Like what if they passed in an array for a, and then my code tried to add the integer and the array together? That won't push the int too the array will it?
Sorry for being a bit questiony, I've been looking for an answer for a while on the Google... And it's getting late here.
Thanks for any help
Uneveris
So, my question is if you need to intialize the varialbes you pass into your class function constructor method-thing.
Do they need initializing, no. Javascript is a loosely typed language and declared variables can be of any type.
You do not need to declare a variable type for the arguments, they can be anything. Also note the vars are private variables in the scope of the constructor.
Now how does the method in Javascript know what type of data structure it is being passed too?
As a result of loose types, javascript has a type typeof to help work out what a variables type actually is if strong typing is required.
if (typeof this.a !== 'function')
throw "Expected a function, received a " + typeof this.a;
Verbose, but it fulfils its purpose.
typeof reference
Like what if they passed in an array for a, and then my code tried to add the integer and the array together? That won't push the int too the array will it?
Have you tried to do this?
var a = new Array();
var b = 1;
var c = a + b;
console.log(typeof c);
>> string
In Node.js the output is a string with the array values concatenated and the integer appended as a string on the end.
It is important when expecting a specific data structure that data you have been passed is what you are expecting. In JS, this is by conditionally checking.
If you are writing these classes purely for your self, duck typing can be useful. If it looks like a duck, quacks like a duck then it is a duck. This is to do with semantics when working in a loosely typed language like JS. Two assumptions === true.
What is duck typing
Hope this helps answer your questions.
You can't be sure what parameter types are being passed to your method. That is a main Javascript language trait which can be used for both good and bad.
So, what happens if there are wrong parameter types? Javascript will try to silently convert them to something common.
For example:
var a = [100,2,3];
var b = 5;
var c = a + b;
Adding an array and an integer (as well as string) will result in a string "100,2,35". Note that array is first converted to String, then 5 is simply appended to the end. This behaviour closely resembles the Java's one, that calls a toString() method of any object whenever it needs to concatenate.
You can avoid the wrong types in two ways. First, convert them yourself. Like,
a = Number.parseInt(a, 10); // now a is of type number
Second, if your method is important and highly dependent on the data correctness, you should not convert the params but avoid using them at all if they are of wrong type:
if (typeof a != "number") throw "Param must be int";
Finally, you can see this JS framework that supports strict typing:
http://betterjs.org/
I am trying one of the examples from the book 'Java Script the Good Parts'. Find below the code.
It throws an error saying Number has no method integer. Could you please help me understand the problem.
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Number.method('integer', function () {
return Math[this < 0 ? 'ceiling' : 'floor'](this);
});
After running the above code, it attaches a method integer to Number.prototype
Number.prototype.integer
It displays the function.
Number.integer
It says undefined.
Number.integer(10);
I get - Number() { [native code] } has no method 'integer'
I am not sure where I am going wrong.
I tried by replacing ceiling with ceil. Still it does not work.
You're adding the method to the prototype assigned to Number instances, you're not adding it to the Number function itself.
So to use it, you call the method on an instance of Number, like this: Live Example | Live Source
var n = 3.1415;
var i = n.integer();
console.log("i = " + i); // "i = 3"
Or with a numeric literal: Live Example | Live Source
console.log(3.1415.integer()); // "3"
console.log((3).integer()); // "3"
Note that in the second line above, I had to put the 3 on its own in parens; otherwise, the JavaScript parser thinks the . is a decimal point rather than a property accessor.
Side note: Extending the prototypes of predefined types with enumerable properties can be a bit hazardous. I've never seen any significant problems when people extend Number or String, but there are major problems if you extend Array or Object, so I would stay away from doing that.
Side note 2: In my examples above, I've also corrected the name of Math.ceil (it's ceil, not ceiling).
The method function (which is taken from Javascript the Good Parts) which you are adding to the prototype of Function helps you define a method on given class or type so that all instances or objects of that type inherit that method.
Two problems in your code:
You are calling integer as if it were defined on the class or constructor function Number itself which is not the case, it is defined on the prototype of Number. If the function was actually defined on Number itself, it would have been defined like this:
Number.integer = function() { /* Implementation */ };
You are passing a parameter to the function (i.e. Number.integer(10)), although in the body of the function you aren't dealing with that number, nor you have declared the integer function to accept any parameters. I guess you are confused that this number is being refereed to by the this keyword inside the function but that is not correct.
The method function allows you to define a method on a given type and you can benefit from it like this:
var a = 10.3; // Now a is a Number instance and so it inherits the integer() method
console.log(a.integer()); // call the method on a
You can even call it directly on literals and they will be wrapped automatically by the interpreter, like this:
console.log((32.543).integer());