I am defining an object literal in JavaScript, but when I try to create a property that is a called function, I get a Uncaught ReferenceError: xxx is not defined error.
Here's an example:
var person = {
name : 'Saucy Jack',
convenienceHook : this.getName('some predefined string'),
getName : function(string) {
console.log(this.name + string);
}
};
This errors saying Uncaught ReferenceError: convenienceHook is not defined.
Nor does it work if I assign the property outside the object definition:
var person = {
name : 'Saucy Jack',
getName : function(string) {
console.log(this.name + string);
}
};
person.convenienceHook = person.getName('some predefined string');
person.convenienceHook(); //returns error
What am I missing?
Here:
var person = {
name : 'Saucy Jack',
convenienceHook : getname('some predefined string'),
getName : function(string) {
console.log(this.name + string);
}
};
you’re calling a function called getname that doesn’t exist. getName is not a property on person yet, because getname('some predefined string') has to be evaluated before the object can exist, since it’s part of the object literal. Even if it did exist, though, you still wouldn’t be able to call it as a bare getname, and even if it did, you would have to capitalize getName properly.
Your second approach also just calls person.getName. It looks like you want to make another function that will call getName:
var person = {
name : 'Saucy Jack',
convenienceHook : function() {
return this.getName('some predefined string');
},
getName : function(string) {
console.log(this.name + string);
}
};
What you assigning is not a function, you need for example to return a function from the getName function, so the convenienceHook will be a function:
getName : function() {
return function() {
console.log(this.name);
};
}
The reason your first attempt fails is that this is not person, it's whatever this is in your current scope. could be global, or could be something else if that code is within a function.
This should work
var person = {
name: "Saucy Jack",
convenienceHook: function() { return this.getName("Predefined text") },
getName: function(string) {
string=string||"";
return this.name + string; }
}
Related
I am new at Javascript. I am currently looking at the keyword this and methods and how to return strings.
I am struggling to return a string using the keyword this.
I have successfully created code that returns the string, but the problem is that it shows the error that "the object is already defined".
Here is the exercise I am working on and also the code I have tried to create which fails to return the correct results:
function exerciseTwo(userObj) {
// Exercise Two: You will be given an object called 'userObj'
// userObject will already have a key on it called 'name'
// Add a method to userObj, called 'greeting'.
// Using the keyword 'this', the greeting method should return the following string:
// 'Hi, my name is ' and the users name.
// eg: If userObj has a name: 'Dan', greeting should return: Hi, my name is Dan'
// NOTE: DO NOT create a new object.
// NOTE: DO NOT create a key called name the key is already on the object.
let userObj = {
name: "Lisa",
greeting: function() {
return "Hi, my name is " + this.name;
},
};
console.log(userObj.greeting());
}
//In the first line of code it shows a error which says that "userObj" is already defined. So I do not know how to return the string without creating a new object and creating a key called name.
//Here is another option I tried but it also did not work out:
function greeting() {
this.name = "Lisa";
let result = "Hi, my name is " + this.name;
return result;
},
userObj.greeting();
}
//The exercise should add a greeting method to userObject object.
So if userObj has a name: 'Lisa', greeting should return: 'Hi, my name is Lisa'
The problem is that your local variable has the same name as the function parameter. You're supposed to add a method to the existing variable, not create a new variable. The instructions specifically say "DO NOT create a new object", yet that is what you did.
function exerciseTwo(userObj) {
// Exercise Two: You will be given an object called 'userObj'
// userObject will already have a key on it called 'name'
// Add a method to userObj, called 'greeting'.
// Using the keyword 'this', the greeting method should return the following string:
// 'Hi, my name is ' and the users name.
// eg: If userObj has a name: 'Dan', greeting should return: Hi, my name is Dan'
// NOTE: DO NOT create a new object.
// NOTE: DO NOT create a key called name the key is already on the object.
userObj.greeting = function() {
return "Hi, my name is " + this.name;
};
console.log(userObj.greeting());
}
let obj = {
name: "Joe"
};
exerciseTwo(obj);
function exerciseTwo(userObj){ // The argument for this "exerciseTwo" function has been declared as "userObj"
let userObj = { // Here you are trying to declare another variable "userObj"
name: "Lisa",
greeting: function() {
return "Hi, my name is " + this.name;
}
};
console.log(userObj.greeting());
}
To solve your issue,
- Declare the let userObj = { ... } block outside the "exerciseTwo" function and pass it in as a variable
let lisa = {
name: "Lisa"
};
function exerciseTwo(userObj){ // Whatever variable you pass into this function will be synonymous to `userObj` within this function
userObj.greeting = function () {
return "Hi, my name is " + this.name;
}
console.log(userObj.greeting());
}
exerciseTwo(lisa) // lisa will take the position of `userObj` above
As the exercise says you only have to add the greeting function to the users object. Like this:
let userObj = { name: "Lisa" };
function exercise2(userObj) {
userObj.greetings = function () {
return "Hi, my name is " + this.name;
}
}
exercise2(userObj);
console.log(userObj.greetings());
I am not sure about differences between object literal and constructor function.
function user() {
this.name="john"
this.getName=function (){
return this.name;
};
}
var johnUser=new user();
console.log(johnUser.getName()); // Will console john
What if I want to call getName without creating any objects something like in Java static method/function?
If I can add
user.sayName=function() {
console.log("Hey there");
}
console.log(user.sayName()); //will console Hey there.
How I can access constructor function properties?
The answer is You can't.
You should have read about how context of function works in JS.
When You are using new operator, empty object is being passed as context, that's why You can assign properties of this (which is reference to function context)
When You are calling a function without new operator, context of Your function is eiter global object (window) or undefined. You can print this in function to see what context You have ATM.
What You (probably) want is to create an prototype
Object literal
var user = {
name: "John",
getName: function(){
return this.name;
}
};
Alternatively, this approach won't define an object.
function sayName()
{
return "just a string";
}
function user() {
this.name = 'john';
}
user.prototype.getName = function(){ return this.name; }
var johnUser = new user();
console.log( johnUser.getName() ) // john
console.log( user.prototype.getName()); // undefined
user.prototype.getName = function(){ return 'just a string' }
console.log( johnUser.getName() ) // just a string
console.log( user.prototype.getName());// just a string
user.prototype.getName = function(){ return this.name || 'just a string'; }
console.log( johnUser.getName() ) // john
console.log( user.prototype.getName());// just a string
I have a JavaScript class like this:
Dog = (function() {
var name;
function setName(_name) {
name = _name;
}
return {
setName: setName,
name: name
};
})();
When I run:
Dog.setName('Hero');
Dog.name is always undefined.
I am certainly missing something about JS scoping, but what?
You are returning an object where name property has a value of name at that point in time (which is undefined). The name property of the returned object is not somehow dynamically updated when the name variable inside the IIFE is updated.
There are many ways to handle what you appear to be wanting to do. Here's one:
Dog = (function() {
var name;
function setName(_name) {
name = _name;
}
return Object.defineProperties({}, {
setName: { value: setName },
name: { get: function() { return name; } }
});
})();
This keeps name as a private variable, which can only be set via setName, but provides a getter property for obtaining its value.
The alternative proposed in another answer is equivalent, just a different way of writing it:
return {
setName: function(n) { name = n; },
get name: function() { return name; }
};
Minor point, but in this particular context you don't need parentheses around your IIFE:
Dog = function() { }();
will work fine.
This happens because you assume that setting name in the object retains a reference to the original name variable. Instead, you want to assign it to the current object (which, you might as well ignore the private variable altogether).
Dog = {
name: '',
setName: function(n) {
this.name = n;
}
};
However, if you want to keep name private then you create a getter for it instead.
var Dog = (function() {
var name;
return {
setName: function(n) {
name = n;
},
get name: function() {
return name;
}
};
})();
The easy way to fix this is:
Dog = (function() {
var dog = {
setName: setName,
name: name
};
function setName(_name) {
dog.name = _name;
}
return dog;
}
In your code, you were setting the wrong name variable.
var name;
function setName(_name) {
name = _name;
}
In this function, setName is setting the internal variable name and not the property name. In JavaScript, strings are immutable, so when you change it, it creates a new string, and doesn't update the existing one.
This might be a better pattern for you. You're using the very old ES3 style constructor.
(function(exports) {
function Dog(name) {
this.name = name;
}
Dog.prototype.speak = function() {
return "woof";
};
// other functions ...
exports.Dog = Dog;
})(window);
var d = new Dog('Hero');
console.log(d.name); // "Hero"
You might want to look into ES6 classes too
class Dog {
constructor(name) {
this.name = name;
}
}
let d = new Dog('Hero');
console.log(d.name); // "Hero"
Sounds like you want to make a constructor... Check this sample:
function Dog(prop) {
this.name = prop.name;
this.color = prop.color;
}
var myDog = new Dog({
name:'Sam',
color: 'brown'
});
alert()
console.log('my dog\'s name is: '+myDog.name);
console.log('my dog\'s color is: '+myDog.color);
you can try it here: http://jsfiddle.net/leojavier/ahs16jos/
I hope this helps man...
Use the 'this' keyword.
Dog = (function() {
var name;
function setName(_name) {
this.name = _name;
}
return {
setName: setName,
name: name
};
})();
Dog.setName('Hero');
alert(Dog.name);
(function() {
LoggerBase.prototype.output = function(message) {
console.log('LoggerBase: ' + message);
};
function BookAppLogger() {
LoggerBase.call(this);
this.logBook = function(book) {
console.log('Book: ' + book.title);
}
}
BookAppLogger.prototype = Object.create(LoggerBase.prototype);
}());
In this code the BookAppLogger inherits the prototypes of the LoggerBase object, I think that is clear from the last statement. What I don't understand is the purpose of the LoggerBase.call(this) statement. What does this line do and why is it neccessary?
BookAppLogger.prototype = Object.create(LoggerBase.prototype);
will only add LoggerBase.prototype functions to BookAppLogger.prototype but you cannot inherit the functions/properties that are written inside LoggerBase function. For example if LoggerBase is something like
function LoggerBase () {
this.fname = "First";
this.lname = "Last";
this.fullname = function(){
return this.fname + " " + this.lname;
}
}
LoggerBase.prototype.somefunction = function(){}
If you do not write LoggerBase.call(this) inside BookAppLogger, then only only LoggerBase somefunction is inherited but not fname, lname, fullname
Its just calling the base class constructor
LoggerBase is a function object and the call method of a function can be used to call that function with a specific this value. Calling LoggerBase directly would result in this being the global object, which in a browser is the window object.
function LoggerBase() {
console.log(this);
}
function BookAppLogger() {
LoggerBase.call(this); // will print the book logger
LoggerBase(); // will print the global object
}
BookAppLogger.prototype = Object.create(LoggerBase.prototype);
I'm trying to implement the Revealing Module Pattern but I'm unable to expose a modified private property.
var myRevealingModule = (function(){
var name = 'Diogo';
function setName () {
name = name + ' Cardoso';
}
return {
fullName: name,
set: setName
};
}());
// Sample usage:
myRevealingModule.set();
console.log(myRevealingModule.fullName); // "Diogo" instead of the excepted "Diogo Cardoso".
return {
fullName: name,
set: setName
};
That uses the values of name and setName. It does not create a reference to the variable. Effectively, name is copied.
You need to create a corresponding getName method, to take advantage of closures so that you can keep a reference to a variable.
var myRevealingModule = (function(){
var name = 'Diogo';
function setName () {
name = name + ' Cardoso';
};
function getName () {
return name;
};
return {
fullName: name,
set: setName,
get: getName
};
}());
http://jsfiddle.net/yeXMx/
If your value is an attribute in an object or array, you can export the object or array and the export will be by reference so outside users will see updated changes. It's a little risky since the generic pattern of exporting variables has the scalar/object copy/reference dichotomy.