This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 4 years ago.
am a beginner learning javascript and was playing around with Objects and am wondering why this code is throwing an error.
var a = {
greeting: "Hello",
greet: this.greeting + "John"
}
console.log(a.greet);
While it's been clarified why your code throws an error, I wanted to explain how you could have it instead.
Javascript makes no difference between ordinary functions and constructors, to a class is just a call to new function with any function in front of it.
Therefore, a way the object can reference itself is by using a function body as its definition:
const AClass = function () {
this.greeting = 'Hello'
this.greet = this.greeting + ' John'
}
const a = new AClass()
console.log(a.greet)
Shorthand since you aren't going to create more than one AClass object (at least in your example):
const a = new function () {
this.greeting = 'Hello'
this.greet = this.greeting + ' John'
}()
console.log(a.greet)
Yours doesn't work because of the problems described in the comments.
I'm guessing that you want something like this:
var a = {
greeting: "Hello",
greet: function() {return this.greeting + " John"}
}
console.log(a.greet());
Or like this:
var a = (() => {
var greeting = "Hello"
return {
greeting,
greet: greeting + ' John'
}
})()
console.log(a.greet);
The first one makes greet a function, which means that it will respond to later changes in greeting. The second one creates an object based on the greeting value. But you have to use a local variable for the reference, since your this at the time of construction is not the new object but some outer scope, possibly something like window.
This question you have is explained here: How Do I reference objects proerty at creation
In order to do what you want you can use an object getter.
var b = {
greeting: "Hello",
get greet() { //this a getter that accesses greeting
return this.greeting + " John";
}
}
console.log(b.greet);
Related
This question already has answers here:
Javascript Class Inheritance For Functions
(2 answers)
Call parent method in JavaScript class but stll have access to prototype methods inside object instance?
(5 answers)
Closed 5 years ago.
This is surely trivial question, but I am little confused with JavaScript. I want to call method inside another function. I have spent some time to handle this and all I have got so far is the second piece of code. I would like to know, if there is any similar solution as noted in comment.
function Student() {
this.greeting = function() {
alert('Hi! I\'m student.');
};
};
function Teacher() {
Student.call(this)
this.greeting = function() {
Student.??? // here I want something like "inherited", or call Student.greeting()
alert('and I like apples');
};
};
I want to be sure, there is no another option like prototyping:
function Student() {
};
Student.prototype.greeting = function() {
alert('Hi! I\'m student.');
};
function Teacher() {
Student.call(this);
this.greeting = function() {
Student.prototype.greeting();
alert('and I like apples');
};
};
Thanx
Student is a function, in your case it is also a constructor.
To call "Student" you need to save object returned by call of constructor-function Student
function Teacher() {
var stdnt = new Student()
this.greeting = function() {
stdnt.greeting()
alert('and I like apples');
};
};
Also, in your code Student.call(this) is equivalent to just function call Student() - without creation of new object
Upd2. This call of stdnt from inner function called "closure"
This question already has answers here:
How do I define global variables in CoffeeScript?
(9 answers)
Closed 7 years ago.
I'm learning CoffeeScript I have this code:
class Person
constructor: (#firstName, #lastName) ->
sayHi: () ->
return "Hi, I'm #{#firstName} #{#lastName}"
And is generating this javascript code:
// Generated by CoffeeScript 1.10.0
(function() {
var Person;
Person = (function() {
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.sayHi = function() {
return "Hi, I'm " + this.firstName + " " + this.lastName;
};
return Person;
})();
}).call(this);
I want to create instances of that class, but since it's inside the closure I can't how should I do that?
An option that is slightly less hackish is the # operator (which is the same as this). In a browser environment, this will point to window, in node.js, it will point to exports.
class #Person
constructor: (#firstName, #lastName) ->
sayHi: () ->
return "Hi, I'm #{#firstName} #{#lastName}"
window.Person only works on the browser, the # will work for node and the browser. See https://stackoverflow.com/a/24352630/227299
Alternatively, you can run coffescript with the -b (--bare) option and the wrapping function won't be created.
change a bit declaration of a class
class window.Person
constructor: (#firstName, #lastName) ->
sayHi: () ->
return "Hi, I'm #{#firstName} #{#lastName}"
I wrote following piece of code in order to explore the javascript scope rules
for functions that use the this identifier. I would expect the second invocation
of person.helloFunk() to print the name "Marvin" and the age "very very old" since I
created the attributes navn and age on the function object itself, but it doesn't.
In stead it repeats the same output "Hello, I'm zaphod and I'm 42 years old".
So why is it that this refers to the object that the function is embedded in and not the function itself (which is also an object)?
var sayHello = function() {
return "Hello, I'm " + this.navn + " and I'm " + this.age + " years old.";
}
var person = {navn: 'zaphod', age: 42};
person.helloFunk = sayHello;
console.log(person.helloFunk());
sayHello.navn = 'Marvin';
sayHello.age = 'verry verry old';
console.log(person.helloFunk());
console.log(person.helloFunk.navn);
console.log(person.helloFunk.age);
You are setting members on the function instead of the person object.
If you set thoe person object's member, then "this" in the function will refer to the right data.
person.navn = 'Marvin'
console.log(person.helloFunk()); //will printout "Hello, I'm Marvin and I'm 42 years old."
The simple answer is, "because that is the way JavaScript is supposed to work". this is dynamic and resolves relative to the container (global|window if there is no other container, unless in strict mode, in which case it is undefined).
If you want to change what this points at you can use call, apply, or bind:
// call and apply differ only in how you pass arguments
// In this case, no arguments, so the invocation is the same
person.helloFunk.call(sayHello);
person.helloFunk.apply(sayHello);
var boundHello = person.helloFunk.bind(sayHello);
boundHello();
this does not point to the function itself, but rather to an object that invokes it.
function sayHello() {
return this.hello;
}
sayHello.hello = "hi!";
console.log(sayHello()); //undefined
When you try to run this code:
var sayHello = function() {
return "Hello, I'm " + this.navn + " and I'm " + this.age + " years old.";
}
sayHello.navn = 'Marvin';
sayHello.age = 'verry verry old';
var person = {navn: 'zaphod', age: 42};
person.helloFunk = sayHello;
console.log(person.helloFunk());
this refers to person, not sayHello.
This question already has answers here:
`new function()` with lower case "f" in JavaScript
(3 answers)
Closed 9 years ago.
in this question, I don't want to ask "Function", i want to ask "function" puzzle
<script type="text/javascript">
var test = function() {
alert('a');
};
var test1 = new function() {
alert('b');
};
</script>
why it will pop up the "b"?
Function (p1, p2, ā¦ , pn, body)
When the Function function is called with some arguments p1, p2, ā¦ , pn, body (where n might be 0, that is, there are no āpā arguments, and where body might also not be provided), the following steps are taken:
Create and return a new Function object as if the standard built-in constructor Function was used in a new expression with the same arguments.
check :Is JavaScript's "new" keyword considered harmful?
new function will execute the function, you can use an IIFE (Immediately- Invoked Function Expression) as well:
var test1 = (function() {
alert('b');
}());
new is used for the Factory pattern in Javascript.
It creates and returns an object by executing a constructor function. In your case it doesn't make sense to use new.
Functions which are built to be used as constructors don't require parens, if you aren't passing any arguments:
var Person = function () { this.is_alive = true; },
bob = new Person;
bob.is_alive;
...but any function can be called as a constructor, whether you're using the returned object or not...
new function () { console.log("Bob"); }
this won't save the function anywhere -- it will run it, in place, instantly.
See What is the 'new' keyword in JavaScript? for a basic description of the new keyword.
Essentially, you are calling the constructor to a new object. Let me show you.
var Animal = function(name) {
alert("Animal Created: " + name);
}
jaguar = new Animal("Cool");
The only difference from that and what you did was declare the function in the same line as defining the new object:
jaguar = new function(name) {
alert("Animal Created: " + name);
}
That's why the "b" was printed out.
I was reading about the new JavaScript-like language from Microsoft called TypeScript. In the playground (example section), there is a simple class in TypeScript syntax converted to JavaScript code. Coming from a Java programming background, it was interesting for me to learn how OOP is done in JavaScript as compiled from TypeScript.
The TypeScript code:
class Greeter {
greeting: string;
constructor (message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
var greeter = new Greeter("world");
var button = document.createElement('button')
button.innerText = "Say Hello"
button.onclick = function() {
alert(greeter.greet())
}
document.body.appendChild(button)
And the equivalent JavaScript code:
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
var greeter = new Greeter("world");
var button = document.createElement('button');
button.innerText = "Say Hello";
button.onclick = function () {
alert(greeter.greet());
};
document.body.appendChild(button);
The Typescript part is very similar to Java so I understand that. Now my question is why in JavaScript the body of the Greeter class is embedded in a an anonymous function() call?
Why not write it like this?
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
What is the advantage/disadvantage of each method?
The following is called an Immediately Invoked Function Expression:
(function(){ ... })();
It is used to keep the global scope clean. Though, in this case it isn't necessary since the return value is assigned to a variable Greeter. The only time this pattern is useful is when you want "private" static members.
E.g.:
var Greeter = (function () {
var foo = 'foo', bar = 'bar'; /* only accessible from function's defined
in the local scope ... */
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
This is to allow for private members. In this example, all members are public so your two constructions are equivalent. However, if you want to provide for private members you need to hide them from the calling scope via a closure. Thus if you have a private member like so:
class Greeter {
private greeting: string;
constructor (message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
You would probably get something like this:
var Greeter = (function () {
var greeting="";
function Greeter(message) {
greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + greeting;
};
return Greeter;
})();
The greeting variable will be available to any function defined inside the anonymous function, but invisible everywhere else.
Besides the obvious scoping/closure reasoning. Using an anonymous function that invokes itself immediately pre-loads (interprets) the class definition. This allows any JIT optimizations to be front loaded within the execution. In short, for larger more complex applications it will improve performance.
The anonymous function / self executing closure is usually used to encapsulate scope so that only the returned value is accessible outside of it. (or anything you attach to other objects, like window)
The anonymous function is probably there to prevent name collition with other parts of the code. Think of it this way, inside your anonymous function, you could even declare a variable called "$" to be whatever you want, and at the same time, be using jQuery on other parts of your code without conflict.
The closure is the sole mean to call the constructors with parameters:
var w = new Greeter("hello")
There are other methods but all complicated and with limitations and drawbacks.