Function and function group with same name in javascript object - javascript

I have following object in JavaScript. I am confused in how to access object.demo() and object.demo.inner(). The object.demo.inner() worked fine but object.demo is not working. I have the requirement that the name should be same. Why is the function not overloading here?
var object = {
// object.demo()
demo: function(str, pathStr) {
console.log('function 1')
},
demo: {
// object.demo.inner()
inner: function () {
console.log('inner')
}
}
}
object.demo.inner() //working
object.demo() //not working

Function is an object in javascript so it can have other properties. So you can assign inner function to a property of object.demo object:
var object = {
// object.demo()
demo: function(str, pathStr) {
console.log('function 1')
}
}
// object.demo.inner
object.demo.inner = function () {
console.log('inner')
}

Actually there is no function object.demo, because you are overwriting the same object with another object. This behaviour is prohibited in ES5 with 'strict mode', but not in ES6.
You could take the outer object and assign the function to the inner property later.
var object = {
demo: function(str, pathStr) {
console.log('function 1')
}
};
object.demo.inner = function () { console.log('inner'); };
object.demo.inner();
object.demo();

Related

Why do we use functionName: function in javascript return statement

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.

'this' and my variables are undefined in my loops [duplicate]

I'm iterating through an array using forEach in one of my Class's methods. I need access to the instance of the class inside the forEach but this is undefined.
var aGlobalVar = {};
(function () {
"use strict";
aGlobalVar.thing = function() {
this.value = "thing";
}
aGlobalVar.thing.prototype.amethod = function() {
data.forEach(function(d) {
console.log(d);
console.log(this.value);
});
}
})();
var rr = new aGlobalVar.thing();
rr.amethod();
I have a fiddle I'm working on here: http://jsfiddle.net/NhdDS/1/ .
In strict mode if you call a function not through a property reference and without specifying what this should be, it's undefined.
forEach (spec | MDN) allows you to say what this should be, it's the (optional) second argument you pass it:
aGlobalVar.thing.prototype.amethod = function() {
data.forEach(function(d) {
console.log(d);
console.log(this.value);
}, this);
// ^^^^
}
Alternately, arrow functions were added to JavaScript in 2015. Since arrows close over this, we could use one for this:
aGlobalVar.thing.prototype.amethod = function() {
data.forEach(d => {
console.log(d);
console.log(this.value);
});
}
Since you're using strict mode, when a function is called that isn't a property of an object, this will have the value undefined by default (not the global object). You should store its value manually:
var aGlobalVar = {};
(function () {
"use strict";
aGlobalVar.thing = function () {
this.value = "thing";
};
aGlobalVar.thing.prototype.amethod = function () {
var self = this;
data.forEach(function (element) {
console.log(element);
console.log(self.value);
});
};
})();
var rr = new aGlobalVar.thing();
rr.amethod();
Nowadays, with ES2015 you can also use arrow functions, which uses the this value of the outside function:
function foo() {
let bar = (a, b) => {
return this;
};
return bar();
}
foo.call(Math); // Math
T.J. Crowder's solution of using the second argument of forEach also works nicely if you don't like the idea of the temporary variable (ES5 code: works in pretty much any browser these days, except IE8-).
What I had to to is add this in the every forEach that I was using (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach ). Binding in the constructor is not needed, as I am using arrow functions. So now my code is:
resetPressed = () => {
this.transport_options.forEach(function (transport_option) {
this.pressed_percentages.forEach(function (percentage) {
filters[transport_option][percentage] = false;
}, this)
}, this);
filters.isFilterActive = false;
this.setState({
filtersState: filters,
opacity: filters.isFilterActive ? 1 : 0.5
});
}
<TouchableHighlight
underlayColor={'transparent'}
onPress={this.resetPressed}
style={styles.iconView}>

scope of "this" in async function of ionic angular app

I'm trying to execute a function, which is not found, UNLESS I save a reference to the function in a seperate variable:
function updateCheck() {
if (this.isNewVersionNeeded()) {
var buildFunc = this.buildObject();
this.updateBiography().then(function(){
buildFunc();
})
}
};
The buildObject function only executes if I save it before executing this.updateBiography (async function) and execute it via the variable I saved it in (buildFunc).
The following does NOT work:
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
this.buildObject();
})
}
};
I expose all functions via a service object:
var service = {
all: all,
updateBiography: updateBiography,
get: get,
updateCheck: updateCheck,
isNewVersionNeeded:isNewVersionNeeded,
buildObject:buildObject
};
return service;
When I log the "this" object while Im right before the execution of buildFunc, it logs window/global scope. Why is this and how should I deal with this? I do not want to save all my async methods in a seperate variable only to remember them. How should I deal with this problem and why does it not work?
The entire service:
(function () {
angular
.module('biography.services', [])
.factory('Biography', Biography);
Biography.$inject = ['$http'];
function Biography($http) {
var biographyObject = { } ;
var service = {
all: all,
updateBiography: updateBiography,
get: get,
updateCheck: updateCheck,
isNewVersionNeeded:isNewVersionNeeded,
buildObject:buildObject
};
return service;
var self = this;
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
self.buildObject();
})
}
};
function updateBiography() {
return $http.get("Apicall adress")
.then(function (resp) {
window.localStorage.setItem('biography', resp.data);
window.localStorage.setItem('biographyTimeStamp', Date.now());
}, function (err) {
console.log('ERR', err);
});
}
function all() {
return biographyObject;
}
function get(name) {
var biography = biographyObject;
for (var i = 0; i < biography.length; i++) {
if (biography[i].name === name) {
return biography[i];
}
}
return null;
}
function buildObject() {
var temp = JSON.parse(window.localStorage.getItem('biography'));
biographyObject = temp;
};
function isNewVersionNeeded() {
prevTimeStamp = window.localStorage.getItem('biographyTimeStamp');
var timeDifference = (Date.now() - prevTimeStamp);
timeDifference = 700000;
if (timeDifference < 600000) {
return false;
}
else {
return true;
}
}
}
})();
The context (different from function scope) of your anonymous function's this is determined when it's invoked, at a later time.
The simple rule is - whatever is to the left of the dot eg myObj.doSomething() allows doSomething to access myObj as this.
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function() {
// whichever object has this anonymous function defined/invoked on it will become "this"
this.buildObject();
})
}
};
Since you're just passing your function reference, you can just use this
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(this.buildObject);
}
};
and if this.buildObject is dependent on the context (uses the this keyword internally), then you can use
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(this.buildObject.bind(this));
}
};
this is determined by whatever context (object) the function is invoked on, and it appears that an anonymous function, or a function not referenced through an object defaults to having a window context. the bind function replaces all instances of this with an actual object reference, so it's no longer multi-purpose
same function invoked in different contexts (on different objects)
var obj = {
a: function () {
console.log(this);
}
};
var aReference = obj.a;
aReference(); // logs window, because it's the default "this"
obj.a(); // logs obj
The reason is here 'this' refers to callback function.You can't access 'this' inside callback.Hence solution is,
function Biography($http) {
var self = this;
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
self.buildObject();
})
}
};
Using ES6 syntax:
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(()=>{
this.buildObject();
})
}
};

Determine if a JavaScript function is a bound function

Is there a way to determine if a JavaScript function is a bound function?
Example:
var obj = {
x:1
};
function printX() {
document.write(this.x);
}
function takesACallback(cb) {
// how can one determine if this is a bounded function
// not just a function?
if (typeof cb === 'function') {
cb();
}
}
takesACallback(printX.bind(obj)); // 1
takesACallback(printX); // undefined
Perhaps this is an important point. I am not asking why the second call prints undefined.
Both bound functions and arrow functions do not have a prototype property:
typeof (function() {}).prototype // 'object' as usual
typeof (function() {}).bind(null).prototype // 'undefined'!
typeof (() => {}).prototype // 'undefined'!
This is not 100% safe since you could still manually assign this property (although that'd be weird).
As such, a simple way to check for bindability would be the following:
// ES5
function isBindable(func) {
return func.hasOwnProperty('prototype');
}
// ES6
const isBindable = func => func.hasOwnProperty('prototype');
Usage:
isBindable(function () {}); // true
isBindable(() => {}); // false
isBindable(
(function () {}).bind(null)
); // false
This way you can make sure that the function that has been passed can deal with a dynamic this.
Here is an example usage for which the above fails:
const arrowFunc = () => {};
arrowFunc.prototype = 42;
isBindable(arrowFunc); // true :(
Interestingly, while bound functions do not have a prototype property they can still be used as constructors (with new):
var Animal = function(name) {
this.name = name;
};
Animal.prototype.getName = function() {
return this.name;
};
var squirrel = new Animal('squirrel');
console.log(squirrel.getName()); // prints "squirrel"
var MutatedAnimal = Animal.bind({}); // Radiation :)
console.log(MutatedAnimal.hasOwnProperty('prototype')); // prints "false"
var mutatedSquirrel = new MutatedAnimal('squirrel with two heads');
console.log(mutatedSquirrel.getName()); // prints "squirrel with two heads"
In that case, the original function prototype (Animal) is used instead.
See JS Bin, code and link courtesy of Dmitri Pavlutin.
This of course won't work with arrow functions since they can't be used as constructors.
Unfortunately, I don't know if there is a way to distinguish a bound function (usable as constructor) from an arrow function (not usable as constructor) without trying them out with new and checking if it throws (new (() => {}) throws a "is not a constructor" error).
In environments that support ES6, you can check whether the name of the function starts with "bound " (the word "bound" followed by a space).
From the spec:
19.2.3.2 Function.prototype.bind ( thisArg , ...args)
[...]
15. Perform SetFunctionName(F, targetName, "bound").
Of course that could result in false positives if the name of the function was manually changed.
One could override the existing prototype bind, tagging functions that have been bound.
A simple solution. This will likely kill certain optimizations in V8 (and possibly other runtimes) because of hidden classes, though.
(function (bind) {
Object.defineProperties(Function.prototype, {
'bind': {
value: function (context) {
var newf = bind.apply(this, arguments);
newf.context = context;
return newf;
}
},
'isBound': {
value: function () {
return this.hasOwnProperty('context');
}
}
});
}(Function.prototype.bind));
In motion:
(function (bind) {
Object.defineProperties(Function.prototype, {
'bind': {
value: function (context) {
var newf = bind.apply(this, arguments);
newf.context = context;
return newf;
}
},
'isBound': {
value: function () {
return this.hasOwnProperty('context');
}
}
});
}(Function.prototype.bind));
var a = function () {
console.log(this);
};
var b = {
b: true
};
var c = a.bind(b);
console.log(a.isBound())
console.log(c.isBound())
console.log(c.context === b);
a();
c();
You would need to write your own bind function on the prototype. That function would build an index of what has been bound.
You could then have another function to perform a lookup against the object where that index is stored.
Based on previous answers, I create a function to determine:
function isBoundFunction(func) {
if(typeof func.prototype === 'object') return false
try {
new func()
}
catch(e) {
return false
}
return true
}
This function determine three type of functions: 1. original function, whose prototype is object, 2. arrow function, which can not be used as constructor, 3. bound function.
There is a module that can help you solve this problem : bind2.
Here's a use case :
const bind2 = require('bind2');
function testFunc() {
return this.hello;
}
const context = { hello: 'world' };
const boundFunc = bind2(testFunc, context);
console.log(boundFunc.bound); // true
Full disclosure : I wrote this module.

javascript error while creating object

While i am trying to create object like this
new Ext.TitleCheckbox ()
I am getting "not a constructor error"
my Object is
Ext.TitleCheckbox = {
checked:false,
constructor : function() {
},
getHtml : function (config) {
var prop = (!config.checked)?'checkbox-checked':'checkbox-unchecked';
var html = config.title+'<div class="'+prop+'" onclick="Ext.TitleCheckbox.toggleCheck(this)"> </div>';
return html;
},
toggleCheck : function (ele){
if(ele.className == 'checkbox-checked') {
ele.className = 'checkbox-unchecked';
}
else if(ele.className == 'checkbox-unchecked') {
ele.className = 'checkbox-checked';
}
},
setValue : function(v){
this.value = v;
},
getValue : function(){
return this.value;
}
};
whats the mistake in here?
Ext.TitleCheckbox is not a function, you cannot make a function call to an object literal.
If you want to use the new operator, you should re-structure your code to make TitleCheckbox a constructor function.
Something like this (assumming that the Ext object exists):
Ext.TitleCheckbox = function () {
// Constructor logic
this.checked = false;
};
// Method implementations
Ext.TitleCheckbox.prototype.getHtml = function (config) {
//...
};
Ext.TitleCheckbox.prototype.toggleCheck = function (ele) {
//...
};
Ext.TitleCheckbox.prototype.setValue = function (v) {
//...
};
Ext.TitleCheckbox.prototype.getValue = function () {
//...
};
See CMS's answer for why. As a work-around, if you really need to do this, you can do it via inheritence. In javascript Constructors inherit from objects (a constructor is just a function). So:
function MyCheckbox () {} ; /* all we really need is a function,
* it doesn't actually need to do anything ;-)
*/
// now make the constructor above inherit from the object you desire:
MyCheckbox.prototype = Ext.TitleCheckbox;
// now create a new object:
var x = new MyCheckbox();

Categories

Resources