Javascript: Object Literal reference in own key's function instead of 'this'
Both can be problematic.
var obj = {
key1: "it",
key2: function(){ return this.key1 + " works!" }
};
var func = obj.key2;
alert(func()); // error
When func
is not called as a method of obj
, this
can reference something else (in here: the global object "window
").
var obj = {
key1: "it",
key2: function(){ return obj.key1 + " works!" }
};
var newref = obj;
obj = { key1: "something else"; };
alert(newref.key2()); // "something else works"
In here we access the object from another reference, though the obj
in the function may now point to some other object.
So you will have to choose which case is more likely. If you really want to make it safe, prevent obj
from being exchanged:
// ES6 - use `const`:
const obj = {
key1: "it",
key2: function(){ return obj.key1 + " works always!" }
};
// ES5: use a closure where the `obj` is stored in a local-scoped variable:
var obj = (function(){
var local = {
key1: "it",
key2: function(){ return local.key1 + " works always!" }
};
return local;
})();
or you bind()
the function to the object:
var obj = {
key1: "it",
key2: function(){ return this.key1 + " works always!" }
}
obj.key2 = obj.key2.bind(obj);
How can a JavaScript object refer to values in itself?
Maybe you can think about removing the attribute to a function. I mean something like this:
var obj = {
key1: "it ",
key2: function() {
return this.key1 + " works!";
}
};
alert(obj.key2());
Self-references in object literals / initializers
Well, the only thing that I can tell you about are getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
Javascript literal object, reference to itself
Following up on Qeuntin's response you would use the following to achieve what you're looking for
var foo = {
self: false,
init: function(){
self = this
self.doStuff();
},
doStuff: function(){
alert('doing stuff');
},
}
EDIT: Since it's been pointed out that whilst this solves OP's problem (i.e it works) it isn't exactly how you should go about it. So, here's a scoping reference.
function A()
{
//Semi-private / hidden var
var pVar = "I'm a private, err hidden, variable",
//fn (technically a var)
pFn = function(){},
//empty var, placholder for hidden fn
privatePlaceholderFn;
//Instance-time... public fn
this.instancePublicFn = function()
{
console.log("--- instace public ---");
//Print hidden var to cosole
console.log(pVar);
//Call hidden fn
instancePrivateFn();
console.log("--->Setting private from instance public")
//Set the hidden fn
setPrivate();
console.log("--- / instance public ---");
}
//Pass fn to private method.
this.setPrivFromOutside = function(fn)
{
setPrivateFromPrivateYetOutside(fn);
}
//Set the hidden fn
this.iPFnPlaceholderSetter = function(fn)
{
privatePlaceholderFn = fn;
}
//Call the semi-private / hidden fn
this.callPrivate = function()
{
privatePlaceholderFn();
}
//A misnomer, proves the scope exists. See "function setPrivate()"
this.setPrivateFromInstance = function()
{
//Prove scope exists
console.log(privatePlaceholderFn);
console.log("Private From instance - gets inside scope");
}
//Set hidden fn from private method
function setPrivate()
{
privatePlaceholderFn = function()
{
//Show scope exists
console.log(pVar);
}
}
//Set the hidden fn from hidden method
function setPrivateFromPrivateYetOutside(fn)
{
//fn's scope won't resolve to inside
privatePlaceholderFn = fn;
}
//Private / hidden messager
function instancePrivateFn()
{
//Just loggin' something
console.log("Instance Private method");
}
}
//Add an object method to the prototype
A.prototype.protoPuFn = function(){
console.log("---> Private var from object literal method");
//console.log(pVar)
}
//...
a = new A();
//Add object literal fn
a.objFn = function()
{
console.log("Object literal defined public fn - Gets outside scope");
//console.log(pVar);
}
//Set private / hidden placeholder fn
a.iPFnPlaceholderSetter(function()
{
console.log("Hidden fn, passed through instance public - gets outside scope");
//console.log(pVar);
});
//Attempt to read hidden var
console.log(a.pVar);
//Call object literal defined fn
a.objFn();
//Call the hidden fn
a.callPrivate();
//Call prototype added fn
a.protoPuFn();
//Call instance added public fn
a.instancePublicFn();
//Call private / hidden method (set
a.callPrivate();
//Same as iPFnPlaceholderSetter except the param is passed to a hidden method, before seting.
a.setPrivFromOutside(function()
{
console.log("-->Passed from outside, through public then private setters");
//console.log(pVar)
})
//Call the hidden method
a.callPrivate();
//Set hidden fn from instance public
a.setPrivateFromInstance();
//Call the hidden method.
a.callPrivate();
//Use evi(a)l fn to steal scope.
a.evil("this.meth = function(){console.log(pVar)}");
//Call fn with stolen scope
a.meth();
Javascript object literal return function as key not working
The misunderstanding here seems to be that your object's keys point to functions that are evaluated upon access. This is not the case. Every time popCategoryResponse
is called, you are creating an object whose keys are the result of evaluating toaster.pop(...)
.
Here is an example if you want to convince yourself of that:
const toaster = [1,2,3,4,5]
// you expect to 'pop' once
// when in fact, it 'pop's three times
const fn = key => ({
a: toaster.pop(),
b: toaster.pop(),
c: toaster.pop()
})[key]
fn('a')
console.log(toaster) // -> [1, 2]
fn()
console.log(toaster) // -> []
reference function in object in another key function
You can define module.exports
at first in a variable and use it in second
as follows:
First file (other.js):
const _this = (module.exports = {
first: () => {
console.log("first");
},
second: () => {
_this.first();
}
});
Second file (index.js):
import other from "./other";
other.second();
Output:
first
functions as a property in objects : referencing other properties inside of your function
You can do it using this
keyword
someObj = {
property : 44,
calculate : function(){
this.property * this.moreproperties;
};
if you have another function like callback for an event in jQuery store this
into variable
someObj = {
property : 44,
calculate : function(){
var parent = this;
$('#some-element').click(function() {
parent.something * parent.somethingElse
});
};
Is this Javascript object literal key restriction strictly due to parsing?
The limitation of the literal object syntax is that the names has to be literal. As the names can be specified as an identifer as well as a string, it's not possible to use a variable instead.
This will create an object with a property n
, not a property answer
:
var n = 'answer';
var o = { n: 42 };
How does the this keyword in Javascript act within an object literal?
Javascript is a late binding language. In fact, it is very late binding. Not only is this
not bound during compile time, it is not even bound during runtime (as most other late binding languages do). In javascript, this
is bound during call time.
The binding rules are quite different from most other OO languages which is why it seems to confuse a lot of people not familiar with javascript.
Basically, how and where you use this
in the code does not affect how this
behaves (it does not matter if it's a standalone function, an object literal etc.) what determines the value of this
is how you call the function.
The rules are:
1 - When a function is called as a constructor, a new object is created and this
is bound to that object. For example:
function Foo () {
this.bar = 1; // when called with the new keyword
// this refers to the object just created
}
new Foo().bar;
2 - When called as an object method this
refers to the object the method belongs to. Basically the name before the last dot. For example:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this refers to foo when called as foo.baz()
}
foo.baz();
3 - If used outside of any function or if a function is not called as a method this
refers to the global object. The javascript spec doesn't give a name to the global object apart from saying that one exists but for browsers it is traditionally called window
. For example:
bar = 1;
alert(this.bar); // this refers to the global object
foo = {
bar: this.bar // also global object
}
function foofoo () {
alert(this.bar); // also refers to the global object
}
foofoo();
4 - In an event handler (such as onclick etc.) this
refers to the DOM element that triggered the event. Or for events not associated with the DOM like setTimeout
or XMLHTTPRequest
, this
refers to the global object. For example:
foo.bar = 1;
foo.baz = function () {
alert(this.bar); // this would normally be foo but if this
// function is assigned to an event it would
// point to the element that triggered the event
}
somediv.bar = 2;
somediv.onclick = foo.baz; // clicking on somedive alerts 2 instead of 1
5 - Finally, when a function is called using either the call()
or apply()
methods this
can be reassigned to anything whatsoever (google "mdn function.prototype.call"). In this way, any object in javascript can borrow/steal another objects' methods. For example:
cat = {
type: "cat",
explain: function () {
return "I am a " + this.type;
}
}
dog = {
type: "dog"
}
cat.explain.call(dog); // returns "I am a dog"
With Function.bind()
in modern javascript implementations we now have another rule:
6 - Functions can also explicitly bind this
to an object using the bind()
method. The bind
method returns a new instance of the function where this
is bound to the argument passed to bind
. For example:
function explain () {
return "I am a " + this.type;
}
dog = {
type: "dog"
}
var dog_explain = explain.bind(dog);
dog_explain(); // returns "I am a dog"
ECMAscript 5 introduced strict mode which changes the meaning of this in functions that isn't called as a method or called with call or apply so we have to add a new rule:
7 - When in strict mode, this
isn't allowed to refer to the global object (window in browsers). So when a function is not called as a method or this
isn't bound to anything manually via call
or apply
or bind
then this
becomes undefined
:
"use strict";
function foo () {
return this;
}
foo(); // returns undefined instead of the global object
ECMAscript 6 introduced arrow functions. Arrow functions change how this behaves by binding early.
8 - In arrow functions, this
is bound at the time the function is declared. So this
in the following code:
var x = () => {return this};
behaves as if the function is declared like the following code:
var x = function () {return this}.bind(this);
Note that since the this
in arrow functions are bound at the time the function is declared you can't use arrow functions if you want to use inheritance. That's because the this
in the function will always point to the parent object and will never point to the child object. That means that the only way to make inheritance work with arrow function is to override all arrow functions from the parent object.
How to create a method in object literal notation?
Syntactically, the change is very simple :
var bob = {
age: 30,
setAge: function (newAge) {
bob.age = newAge;
}
};
But as you can see, there's a problem : as in your code it uses the external bob
variable so this wouldn't work if you change the value of the bob
variable.
You can fix that with
var bob = {
age: 30,
setAge: function (newAge) {
this.age = newAge;
}
};
Note that at this point you should check whether what you need isn't, in fact, a class, which would bring some performance improvements if you have several instances.
Update: ECMAScript 6 now allows methods to be defined the same way regardless of whether they are in an object literal:
var bob = {
age: 30,
setAge (newAge) {
this.age = newAge;
}
};
Related Topics
No Visible Cause For "Unexpected Token Illegal"
Changing the Image Source Using Jquery
Jquery Scroll() Detect When User Stops Scrolling
Using JavaScript to Edit CSS Gradient
Serving Gzipped CSS and JavaScript from Amazon Cloudfront via S3
Unable to Scroll in Scrollview
Detect iOS Version Less Than 5 with JavaScript
Why Doesn't Indexof Work on an Array IE8
Take a Screenshot of a Webpage With JavaScript
How to Set the Caret (Cursor) Position in a Contenteditable Element (Div)
I Keep Getting "Uncaught Syntaxerror: Unexpected Token O"
Converting JavaScript Object With Numeric Keys into Array
Regex to Extract All Matches from String Using Regexp.Exec
How to Preserve Aspect Ratio When Scaling Image Using One (Css) Dimension in IE6