I have a function here, inside that function, there's a helper function. Right now my error is pointing to the first bracket of my display function.
function main() {
// Array of objects
// Sorted those objects
display() { <---Error here
}
}
There's an array of objects where I mapped what I needed and sorted them. After that within that same function, this display function should show up on the DOM, but am getting unexpected token {
What am I missing?
ANSWER
Thanks to everyone, I understand where my confusion was. In some instances, specifically when dealing with classes, I saw that the function keyword was omitted whenever declaring functions within that class.
That is possible due to prototype inheritance I believe and in any other case the function keyword is needed.
It dosen't work since display() is calling (the non-existing) function display. (you can only use that kind of declaration in an object).
Below you see other ways to declare the function:
function main() {
// Array of objects
// Sorted those objects
display() { <---Error here because it is calling a function
}
function display2() {
// this works
}
const display3 = () => {
// this works too.
}
var display4 = function() {
// this wors too, as suggested by Sagar V 2
}
}
update
You can omit the function keyword when defining functions in an object initializer:
const myObject = {
traditionalWay: function() {
},
newWay() {
}
}
Related
Using this keyword inside functions of an object works, but refering to other functions without this doesn't. When I put out those functions before the object, both ways work. Why is that so?
var Obj = {
func1: function () {
console.log(this.func2()); // works
console.log(func2()); // doesn't work
},
func2: function () {
return 5;
}
};
Obj.func1();
But doing the same in IIFE:
var Obj = (function () {
function func1() {
console.log(this.func2()); // works
console.log(func2()); // works
}
function func2() {
return 5;
}
return {
func1: func1,
func2: func2
};
})();
Obj.func1();
This has nothing to do with the IIFE, in the first example you have an object literal, in the second regular functions.
Of course, object literals would need the name of the object (or this if the this-value is the object, like inside an object literal) followed by the property to access it, while named functions can be accessed anywhere in that scope by just using the name.
var obj = {
prop : function() {...}
}
prop(); // fail ... undefined
obj.prop(); // works
// then _______________________________________________________________
function prop() {...}
prop(); // works fine
This is really what you're doing, you've just wrapped it up in different objects and immediately invoked function expressions, so it looks somewhat the same, but it's not.
There is no difference.
In both cases, you're working with an object. So, you need to use this or the object name to call the function defined under an object.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
I am using Typescript for an Angular 2 project. I notice that when we use the keyword this inside a labmda expression vs a function, this refers to different things.
For example, let's say I have an Angular component like the following.
export class MyComponet {
isActive = true;
names = [ "john", "jeff", "jared" ];
doSomethingWithLambda() {
names.forEach( (value, index) => {
if(this.isActive) { //this.isActive refers to MyComponent.isActive
//do something...
}
});
}
doSomethingWithFunction() {
names.forEach( function(value, index) {
if(this.isActive) { //this.isActive is undefined, since this refers to the function
//do something
}
});
}
doSomethingWithFunction2() {
let isActive = this.isActive;
names.forEach( function(value, index) {
if(isActive) { //if we change isActive will this also change MyComponent.isActive?
//do something
}
});
}
}
What is really happening here (behind the scene, so to speak)? What's the magic behind this inside a lambda that makes it able to "correctly" refer to the outer class' fields? I understand this inside a function will refer to the function itself.
Also, I have a doSomethingWithFunction2 method that will reference MyComponent.isActive into a local variable. If I change that local variable, that should be like changing the one it references, right? (regardless of it being a "primitive" like integer/number or an "object" like JSON { })
The fat-arrow function syntax is shorthand for:
function () { }.bind(this);
bind is a Javascript ES5 method equivalent to this:
Function.prototype.bind = function bind(context) {
var func = this;
return function () {
return func.apply(context, arguments);
};
}
In regards to
Also, I have a doSomethingWithFunction2 method that will reference MyComponent.isActive into a local variable. If I change that local variable, that should be like changing the one it references, right? (regardless of it being a "primitive" like integer/number or an "object" like JSON { })
In Javascript, variables are like pointers and except for some limited cases (primitives and copy-on-write objects) will change the referenced value when mutated. Reassigning will not change the original value, e.g. isActive = false; but this.isActive = false would in fact re-assign the variable isActive on this which is now hopefully correctly assigned.
This has to do with how lambda function are implement in TS. this in arrow function is lexically inferred so it more in line with below code
function Person() {
var self = this; // Some choose that instead of self.
// Choose one and be consistent.
self.age = 0;
setInterval(function growUp() {
// The callback refers to the self variable of which
// the value is the expected object.
self.age++;
}, 1000);
}
So inside the lambda function it is not actually this but a context closer self. This may not be actual implementation but much closer to give you understanding of what is happening.
Now when you are outside the my impotent this refers to global var which would be window
The lambda function is similar to javascripts bind function.
Protip see your transpiled JS how your lambda function is transforming.
I recently search in the code of the library of knockout to find how observables are able to create dependencies with computed functions when we call it.
In the source code, I found the function linked to observables creation:
ko.observable = function (initialValue) {
var _latestValue = initialValue;
function observable() {
if (arguments.length > 0) {
// Write
// Ignore writes if the value hasn't changed
if (observable.isDifferent(_latestValue, arguments[0])) {
observable.valueWillMutate();
_latestValue = arguments[0];
if (DEBUG) observable._latestValue = _latestValue;
observable.valueHasMutated();
}
return this; // Permits chained assignments
}
else {
// Read
ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
return _latestValue;
}
}
ko.subscribable.call(observable);
ko.utils.setPrototypeOfOrExtend(observable, ko.observable['fn']);
if (DEBUG) observable._latestValue = _latestValue;
observable.peek = function() { return _latestValue };
observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
ko.exportProperty(observable, 'peek', observable.peek);
ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
return observable;
}
What I think is very weird is the returns of 'observable' where I don't found any declaration of this variable. Sure that great men who created this library don't forget to declared it.
How it is possible to use a variable without declared it and prevent it to be put in a global scope?
My feeling is we can used a function declaration as a variable when this function declaration is declared inside another function but I'm really not sure about how it works.
Edit:
After searching on the web, I found this article.
In this article, the guy write this:
Use declarations, please
"In the code of unexperienced developers, functions are often declared by expressions:
... code ... var f = function() { ... } ...
Function Declarations are much more readable and shorter. Use them instead.
... code ... function f() { ... } ...
Besides, functions declared this way can be called before it’s definition.
Use expressions only if you mean it. E.g for conditional function definition."
Ok, Am I an unexperienced developer? I don't think so. I just don't read all the odds of Javascript. :)
observable is a variable. It is declared by a function declaration.
function observable() {
...
}
In Javascript, functions can also be returned. Within the function, he defines the function "observable" which is returned at the end of the function.
Sort to speak, functions are variables too. With a function inside.
Is it possible to create an alternate of Array.forEach that automatically sets the context "this" to be the same context as when the method was invoked?
For example (not working, not sure why):
Array.prototype.each = function(fn) {
return this.forEach(fn, arguments.callee.caller);
}
function myFunction() {
this.myVar = 'myVar';
[1,2,3].each(function() {
console.log(this.myVar); // logs 'myVar'
});
}
Array.forEach already takes a context argument as the optional last parameter,
(function() {
this.myvar = "myvar";
[1,2,3,4].forEach(function(v) {
console.log("v:"+v);
console.log("myvar="+this.myvar);
}, this);
})();
See MDN forEach
Also, the above examples (if we're not dealing with methods on instances regarding this) work without using bind or the optional context argument for forEach, the following also works correctly:
function myFunction() {
this.myVar = 'myVar';
[1,2,3].forEach(function() {
console.log(this.myVar); // logs 'myVar'
});
}
myFunction();
Because javascript is functionally scoped, so the anonymous function can access the parent function's scope using this and it logs correctly. this only really becomes problematic as a context when dealing with instance methods.
The answer is no, a JavaScript function cannot determine the value of this in the caller.
You can bind the function passed with the current object, like this
function myFunction() {
this.myVar = 'myVar';
[1,2,3].forEach(function() {
console.log(this.myVar); // logs 'myVar'
}.bind(this));
}
In ECMA Script 6, you can use an Arrow function, like this
[1,2,3].forEach(() => {
console.log(this.myVar); // logs 'myVar'
});
An alternative to messing with the this variable when passing around callbacks, you could always just assign this to a new variable so child scoped functions can access it:
Array.prototype.each = function(fn) {
return this.forEach(fn, arguments.callee.caller);
}
function myFunction() {
var me = this;
me.myVar = 'myVar';
[1,2,3].each(function() {
console.log(me.myVar); // logs 'myVar'
});
}
now you don't have to remember to pass this as a second parameter
Firstly, it must be pointed out that myFunction is a constructor. Yet, the first letter in the identifier is not capitalized. Please call it MyFunction.
If a constructor is called without the new operator, this is bound to the global object, i.e. window in browsers. This makes the capitalization convention our only way of spotting such mishaps.
The following lines of code demonstrate this:
// After the original code...
myFunction();
console.log(window.myVar); // logs "myVar"
Secondly, to be able to apply functions on any array, instead of changing Array.prototype, consider the following:
var utils = {array: {}}; // utils.array is a container for array utilities.
utils.array.each = function (array, func) {
var i;
for (i = 0; i < array.length; i += 1) { func(array[i]); }
};
utils.write = function (s) {
console.log(s); // Alternatively, document.write(s);
};
utils.array.each([1, 2, 3], utils.write); // prints 1 2 and 3 (on separate lines)
Notice that we didn't use this and new. They make JavaScript look like Java, apart from that, they rarely serve a useful purpose.
While libraries may modify Object.prototype and Array.prototype, end-developers shouldn't.
Also, we should (ideally) be able to do something like:
utils.array.each([1, 2, 3], console.log); or
utils.array.each([1, 2, 3], document.write);.
But most browsers won't allow it.
Hope this helped.
If I understand your requirement correctly, then you are trying to override the "this".
I think this can help you.
What does the following javascript code mean? I guess it's defining a function within a function to make it look like OOP? Why the function can return multiple functions? what is the bracket at the end?
var grid_ui = function () {
function setup_data_source() {}
return {
init: function () {},
set_ds: function(rpt_headers, rpt_rows) {}
} // return
}();
The { } notation is called an object literal. It is same as:
a = new Object();
a.init = function() { };
a.set_ds = function(...) { };
return a;
and return { } returns an object.
The function () { ... }(); is a self-invoking function: it creates an anonymous function them immidiately invokes it.
In your code, the self-invoking function returns an object of functions, which is a namespace pattern. The value of grid_ui now contains { init: ..., set_ds: ... }, which is mentioned in return.
These concepts are very difficult to explain in one SO answer, so I will provide you some links:
http://www.hunlock.com/blogs/Functional_Javascript/
http://www.dustindiaz.com/namespace-your-javascript/
it is defining an function then calling it and taking the return value and assigning it to grid_ui.
the value of grid_ui is now the object (also called a dictionary) containing the keys init and set_ds.
In javascript, you can define functions within functions and assign functions to variables.
Now you can make calls like grid_ui.init() and grid_ui.set_ds("test", 1).
It is OOP. Functions are objects in JavaScript.
This code means that there is a variable, grid_ui, which evaluates to an object that has two "public" functions, init and set_ds. init and set_ds also have a context which includes a "private" function, setup_data_source.
There are no brackets.