i am a little confused. i want to create a javascript object like:
function myObject(){
this.keyOne=1;
this.keyTwo=2;
this.keyThree=3;
function add(){
return this.keyOne+this.keyTwo+this.keyThree;
}
return{
add: add
}
}
so creating this object with
var newObject = new myObject();
is working fine and all attributes are correct. but with
var result = newObject.add;
all keys are suddenly undefined! i have no idea why? :/
You're not defining add() in a way that's exposed, you could do this for example:
function myObject(){
this.keyOne=1;
this.keyTwo=2;
this.keyThree=3;
this.add = function(){
return this.keyOne+this.keyTwo+this.keyThree;
}
}
var newObject = new myObject();
var result = newObject.add();
You can test it here.
Also note that you need to call add() with parenthesis, since it's a function, or you'll get the function itself back, not the result.
There currently is no meaning for the keyword public in standard JavaScript.
Based on your original code snippet, I suspect you meant:
function myObject(){
this.keyOne=1;
this.keyTwo=2;
this.keyThree=3;
function add(){
return this.keyOne+this.keyTwo+this.keyThree;
}
return {
add: add
};
}
The function would then return an object that only has one property: the add function. That object is created by the object literal after the return keyword.
But then there is no point using this. You could have written:
function myObject() {
var keyOne=1;
var keyTwo=2;
var keyThree=3;
function add() {
return keyOne + keyTwo + keyThree;
}
return {
add: add
};
}
Or even more succinctly:
function myObject() {
var keyOne=1;
var keyTwo=2;
var keyThree=3;
return {
add: function() {
return keyOne + keyTwo + keyThree;
}
};
}
This has the added advantage that you don't need to call it prefixed with new. It's just an ordinary function that creates and returns an object which contains another function:
var o = myObject();
alert(o.add());
You could allow the caller to specify the numbers to be added, like this:
function myObject(keyOne, keyTwo, keyThree) {
return {
add: function() {
return keyOne + keyTwo + keyThree;
}
};
}
var o = myObject(5, 4, 7);
alert(o.add());
Related
I have the following code.
function Test() {
this.funct_1 = function() {
alert('funct_1');
}
this.funct_2 = function() {
alert('funct_2');
}
return this;}
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return function() {
return testObj;
}}
What I'm trying to accomplish is the following. I want to have a class Test which is not singleton. Then in some other places in my application I need to have a function which could return the same instance per script execution. I figured that I could use closure for that getTestObj.
However, when I try to use it
getTestObj().funct_1();
I'm getting the following error, saying the funct_1() is not found.
Cannot find function funct_1 in object function () {...}.
Clearly, I'm making some kind of mistake here, but I'm not able to find any solution over the net which could help me. Would appreciate any comments.
NOTE: I'm forced to use ECMA5
testObj is wrapped inside a function
So, either call it
getTestObj()().funct_1(); //notice two ()()
Save the value of getTestObj() in a variable
var singleTon = getTestObj();
var testObj = singleTon();
testObj.funct_1();
Or, simply return testObj (in case singleTon isn't required)
function getTestObj()
{
var testObj;
if (!testObj) {
testObj = new Test();
}
return testObj;
}
And invoke it as
getTestObj().funct_1(); //notice single ()
getTestObj() is returning a function i.e. :
function() {
return testObj;
}
So you have to call it again getTestObj()(), this will return the Test's object and now you can access it's properties.
getTestObj()().funct_1();
OR
You can change your getTestObj function as :
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return (function() {
return testObj;
}());
}
I am completely new to javascript. I saw the below snippet in a tutorial. But i am not sure why do we use funtionName: function in return statement.
For example, getID:function() and setID: function() in the below code. Can anybody explain.
function celebrityID () {
var celebrityID = 999;
return {
getID: function () {
return celebrityID;
},
setID: function (theNewID) {
celebrityID = theNewID;
}
}
}
in your celebrityID () function you are returning an object, which has two properties those properties are function.
you can call
var myVar = new celebrityID();
myVar.getID(); // myVar = 999
this like object creation from a class
So they can use it as
var cid = celebrityID();
var celbId = cid.getID();
If you do not have the return statement the function getID() will not be useful and also celbId becomes undefined.
If you closely observe, there is no return statement for setter.
I'm trying to create a mini jQuery clone that can support method chaining. So far I've came up with this piece of code:
var $ = (function () {
var elements = [];
function methodOne() {
console.log('Method 1');
return this;
}
function methodTwo() {
console.log('Method 2');
return this;
}
return {
methodOne: methodOne,
methodTwo: methodTwo
};
}());
At page load, the $ variable gets populated with the jQuery clone object returned by the IIFE.
My question is, how can I make the $ object to be called directly as a function while still maintaining the method chaining functionality?
Right now, I can use $.methodOne().methodTwo() but I cant use $('some parameter').methodOne().methodTwo() just like jQuery does.
var $ = function (param) {
var elements = [];
console.log(param);
function methodOne() {
console.log('Method 1');
return this;
}
function methodTwo() {
console.log('Method 2');
return this;
}
return {
methodOne: methodOne,
methodTwo: methodTwo
};
};
$('This is a param').methodOne().methodTwo();
Working fiddle. The comments should be more or less self explanatory.
It might look a bit long, but it will let you create new mini jQuery object every time you call it.
var _ = (function () {
var Magic = function(query){
if(window === this)
return new Magic(query);
// reference to itself
var that = this;
//assign pseudo public methods and variables
that.elements = [];
that.methodTwo = methodTwo;
that.methodOne = methodOne;
//fills inner element array with DOM element
_get(query);
function _get(query){
var elem = document.getElementById(query);
that.elements.push(elem);
}
function methodOne() {
console.log('Method 1');
return that;
}
function methodTwo() {
console.log('Method 2', that.elements);
return that;
}
return this;
}
//returns function, which is assigned to a "_" variable
return function(query){
//everytime "_" is called, it will return new instance for object Magic which makes all the work
return new Magic(query);
}
}());
Ruby's refinements allow you to temporarily "upgrade" an object within a lexical scope. I'm trying to implement a similar idea in javascript. Here's some working code that does almost what I want:
function dateExtension() {
return {
day: function() { return this.getDate() }
}
}
function refine(ctor, mixin) {
return function() {
var ret = new (Function.prototype.bind.apply(ctor, arguments));
return Object.assign(ret, mixin);
}
}
function test() {
// Cant overwrite native Date function,
// so have to rename it.
var XDate = refine(Date, dateExtension());
var d = new XDate();
console.log(d.day()); // prints the day of the month to console
}
test();
What I really want to do is this:
function test() {
var Date = refine(Date, dateExtension());
var d = new Date();
console.log(d.day()); // Uncaught TypeError: Bind must be called on a function
}
The idea would be to make the local var Date overide the built in Date, within the body of test() only. So that, within test(), it would acquire the new method day(), but outside of test() Date would be unaffected. This apparently is not allowed.
Is there some workaround to make this idea work?
I made a tiny library called chill-patch to do exactly that. It enables you to use functions as methods, and to safely patch prototypes.
Here's an example of how to use it:
const chillPatch = require('chill-patch')
const lastFunc = arr => arr[arr.length - 1]
const array = [1, 2, 3]
// safely add a method to `Array`
const last = chillPatch(Array, lastFunc, 'last')
// call the new method!
array[last]() //=> 3
If you want to roll your own, the entire source code is as follows:
'use strict'
const chillPatch = (klass, func, optionalDescription) => {
const symbol = Symbol(optionalDescription)
klass.prototype[symbol] = function(){
const args = Array.prototype.slice.call(arguments)
args.unshift(this)
return func.apply(null, args)
}
return symbol
};
module.exports = chillPatch
I see you said in a comment that you do not want to modify prototypes, but your reason is probably that modifying prototypes is dangerous. However, the method above patches using Symbol, which is completely safe. The change will be invisible to other parts of the codebase unless someone is doing reflection with Object.getOwnPropertySymbols()
So I came up with something that works, although it's fairly hacky.
Here's a fiddle: https://jsfiddle.net/40cty4qa/
And here's the code
function lg() { console.log.apply(console, arguments) }
function extend(o, mixin) {
for (var k in mixin) o.prototype[k] = mixin[k]
}
function unextend(o, mixin) {
for (var k in mixin) delete o.prototype[k];
}
Function.prototype.refine = function(ctor, mixin) {
var self = this;
return function() {
extend(ctor, mixin);
var ret = self.apply(this, arguments);
unextend(ctor, mixin);
return ret;
}
}
function dateExtension() {
return {
day: function() { return this.getDate() }
}
}
function refine(ctor, mixin) {
return function() {
var ret = new (Function.prototype.bind.apply(ctor, arguments));
return Object.assign(ret, mixin);
}
}
function test() {
var d = new Date();
lg(d.day());
}
test = test.refine(Date, dateExtension());
test(); // This works, since were inside a refinement
var d = new Date();
lg(d.day()); // This doesnt work, as desired.
How must a function be 'chained', in order to call this function like this
F('Test').custom_substring(0,1);
You have to return an object that has a method member named custom_substring. One example:
var F = function(){
return {
custom_substring:function(){
console.log('custom substring');
return this;
}
}
}
F('Test')
.custom_substring(0,1)
.custom_substring(0,1)
.custom_substring(0,1);
To create objects you can use constructor functions and prototype, this is a complex subject and explained here.
I would not mess with the String.prototype because that breaks encapsulation.
The following sample provides a chainable custom_substring that does not modify the original object but instead returns a new one. This is similar to how jQuery and other libraries work (and how built-in string operations work) and it helps make for safer and more predictable code.
function F(str) {
return {
toString: function () { return str; },
// You didn't provide an example of what you want custom_substring
// to do, so I'll have it append a "!" to the beginning of the resulting value
// (since I can't think of anything else for it to do)
custom_substring: function (from, to) {
return F("!" + str.substring(from, to));
}
};
}
var s1 = F("Hello everyone");
var s2 = s1.custom_substring(0, 7);
var s3 = s2.custom_substring(0, 5)
.custom_substring(0, 4);
console.log(s1); // Hello everyone
console.log(s2); // !Hello e
console.log(s3); // !!!He
If you really want to create chainloading you need always return this from methods where it's possible.
For example we have some class with some methods:
function Foo() {
this.foo = 'bar';
return this;
}
Foo.prototype = Object.create({
sayFoo: function() {
console.log(this.foo);
return this;
},
getFoo: function() {
return this.foo; // Here you can't make chainload
},
saySmth: function() {
console.log('Something');
return this;
}
});
And we can use this:
var test = new Foo().sayFoo().saySmth().getFoo(); // prints this.foo -> 'Something' -> returns this.foo
console.log(test); // prints out this.foo