I have little issue accessing object property in typscript. this works fine in js but doesn't in ts
let getUserName = {
firstname : "timi",
lastname: "oluwayomi",
middlename: "ola",
full : () => { return this.firstname + this.lastname + this.middlename } ,
first: () => { return this.firstname }
}
console.log(getUserName.first())
in javascript output: timi
but ts throws error. is there a different way to access it in ts ?
just refer to the same object in the object, this is a hack IMO
let getUserName = {
firstname : "timi",
lastname: "oluwayomi",
middlename: "ola",
full : () => { return getUserName.firstname + getUserName.lastname + getUserName.middlename } ,
first: () => { return getUserName.firstname }
}
console.log(getUserName.first())
this inside arrow function refers to the global object, so its giving error, you can try with traditional functions
let getUserName = {
firstname : "timi",
lastname: "oluwayomi",
middlename: "ola",
full : function() { return this.firstname + this.lastname + this.middlename } ,
first: function() { return this.firstname }
}
console.log(getUserName.first())
i was working on an component based project "Angular"
so i had to initialize first
getUserName : any;
getUserName = {
firstname : "timi",
lastname: "oluwayomi",
middlename: "ola",
full : () => { return getUserName.firstname + getUserName.lastname + getUserName.middlename } ,
first: () => { return getUserName.firstname }
}
console.log(getUserName.first())
also thanks to Dean Van Greunen
You are accessing this within an arrow function. Inside an arrow function, this refers to the global object, not the execution context. See You Don't Know JS Yet - Chapter 3 - this Keyword for more info on this.
So, to start with, use this:
let getUserName = {
firstname : "timi",
lastname: "oluwayomi",
middlename: "ola",
full() { return this.firstname + this.lastname + this.middlename },
first() { return this.firstname },
}
As this is of type any in this case, as the TypeScript compiler cannot infer the type of your object for you, you will need to type the object yourself (usually a good idea anyway):
type GetUserName = {
firstname: string;
lastname: string;
middlename: string;
full(): string;
first(): string;
}
let getUserName: GetUserName = {
firstname: "timi",
lastname: "oluwayomi",
middlename: "ola",
full(this: GetUserName) {
return this.firstname + this.lastname + this.middlename;
},
first(this: GetUserName) {
return this.firstname;
},
};
Related
In React, I have created function mentioned below:
infoPrint (firstname = '--', middlename = '--', surname = '--')
{
console.log('Firstname: ', firstname, ', Middle name: ', middlename, ', Surname: ', surname);
}
I am calling this function in componentWillMount:
componentWillMount() {
var firstname = 'Naisarg';
var surname = 'Parmar';
this.infoPrint(firstname,surname);
}
I am getting this output:
Firstname: Naisarg, Middle name: Parmar, Surname: --
But I'm expecting this one:
Firstname: Naisarg, Middle name: --, Surname: Parmar
You can achieve that by passing a literal object as argument of your function:
class User extends Component {
componentWillMount() {
var firstname = 'Naisarg';
var surname = 'Parmar';
this.infoPrint({ firstname, surname });
}
infoPrint({ firstname = '--', middlename = '--', surname = '--' }) {
console.log('Firstname: ', firstname, ', Middle name: ', middlename, ', Surname: ', surname);
}
}
It's a very common pattern that helps a lot with optional parameters.
-
If you prefer not to use an object, then you must pass all the arguments in the correct order:
class User extends Component {
componentWillMount() {
var firstname = 'Naisarg';
var surname = 'Parmar';
this.infoPrint(firstname, null, surname);
}
infoPrint(firstname = '--', middlename = '--', surname = '--') {
console.log('Firstname: ', firstname, ', Middle name: ', middlename, ', Surname: ', surname);
}
}
To achieve what you require, you will either need to pass -- or null for the middlename argument:
componentWillMount() {
var firstname = 'Naisarg';
var surname = 'Parmar';
this.infoPrint(firstname, null, surname);
this.infoPrint(firstname, '--', surname);
}
or alternatively, you could refactor your method signature by passing these arguments indirectly via an object argument:
function infoPrint(name = { first: '--', middle: '--', last: '--' }) {
console.log('Firstname: ', name.first, ', Middle name: ', name.middle, ', Surname: ', name.last);
}
infoPrint({
first: 'Naisarg',
last: 'Parmar'
});
The "object argument" method shown above resolves the issue you're facing by retaining a (key) relationship between the arguments themselves, and the way in which each keyed argument is actually used in your infoPrint() function.
Without this, the JavaScript run-time has no way of knowing that you intend the surname variable to actually be passed to infoPrint() as the "third surname argument" - simply put, the arguments that you pass are assigned from first to last. Substituting the variable with values as shown below might give more insight as to what's happening, and why your original code doesn't work as expected:
// var firstname = 'Naisarg';
// var surname = 'Parmar';
// Substitute variables with values to better understand how
// arguments are being passed to the function
this.infoPrint(
'Naisarg' /* <-- firstname */,
'Parmar' /* <-- middlename */,
/* no value for surname, so use default "--" */
); /* Prints: "Firstname: Naisarg , Middle name: Parmar , Surname: -- " */
I have code is below, I want my result is "Hello Mr. John Doe".
function formatname(name) {
return name.fullName;
};
const name = {
firstName: 'John',
lastName: 'Doe',
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
};
const getName = (
<h1>Hello Mr. {formatname(name)}</h1>
);
ReactDOM.render(
getName,
document.getElementById('root')
);
But when I save it return is "Hello Mr. ", what I wrong in variable fullName.
In your code:
const name = {
firstName: 'John',
lastName: 'Doe',
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
};
this is not refered to your variable name anymore. To solve, you need to bind this back to the name you declared:
formatname(name).bind(name)()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
Given an object that has a "firstName" property and a "lastName" property, "addFullNameProperty" returns a "fullName" property whose value is a string with the first name and last name separated by a space.
var person = {
firstName: 'Jade',
lastName: 'Smith'
};
addFullNameProperty(person);
console.log(person.fullName); // --> 'Jade Smith'
my code :
function addFullNameProperty(obj) {
// your code here
obj[fullName] = obj.firstName + obj.lastName;
}
Just simple set:
obj.fullName instead of obj[fullName]
Or
obj['fullName']
Because fullName in your code is undefined variable. So JS alert error.
Either use obj.fullName or obj['fullName']
But a more correct solution would be
function addFullNameProperty(obj) {
// your code here
Object.defineProperty(obj, 'fullName', {
get: function(){
return this.firstName + ' ' + this.lastName;
},
configurable:false
});
}
var person = {
firstName: 'Jade',
lastName: 'Smith'
};
addFullNameProperty(person);
console.log(person.fullName); // --> 'Jade Smith'
person.firstName = "Mike";
console.log(person.fullName); // --> 'Mike Smith'
This way your object will always return the correct fullName.
If you want to add the space into the name, you will need to do string interpolation, like so:
`${obj.firstName} ${obj.lastName}`
and complement this with Gaby's answer about switching to dot notation, obj.fullName
Add new property to an existing object:
const person = {
firstName: 'Jade',
lastName: 'Smith'
};
person.fullName = `${person.firstName} ${person.lastName}`;
same as:
person['fullName'] = `${person.firstName} ${person.lastName}`;
or using method:
const person = {
firstName: 'Jade',
lastName: 'Smith',
fullName(){
return `${this.firstName} ${this.lastName}`;
}
};
person.fullName(); // Jade Smith
You can also use defineProperty
Try this
return obj.fullName = obj.firstName + " " + obj.lastName
I`m trying to figure out what is getters and setters in JavaScript.
Here is my object
function User(fullName) {
this.fullName = fullName;
Object.defineProperties(this,{
firstName :{
get: function(){
return this.fullName.split(" ")[0];
},
set :function(value){
this.firstName = value;
}
},
lastName:{
get: function(){
this.lastName = this.fullName.split(" ")[1];
},
set: function(value){
this.lastName = value;
}
},
fullName :{
set: function(value){
this.fullName = value;
}
}
});
}
Then creates a new user:
var user = new User("New User");
But when I`m trying to get the firstName property like
alert( user.firstName )
it throw an error "Cannot read property 'split' of undefined".
What may cause the problem? It looks like 'this' is not visible inside get function, but as I understand it should. Thanks!
You don't need a setter for fullName as direct assignment will work.
function User(fullName) {
this.fullName = fullName || '';
Object.defineProperties(this, {
firstName: {
get: function() {
return this.fullName.split(" ")[0];
},
set: function(value) {
this.firstName = value; // NOTE: This will throw an error
}
},
lastName: {
get: function() {
return this.fullName.split(" ")[1];
},
set: function(value) {
this.lastName = value; // NOTE: This will throw an error
}
}
});
}
var joe = new User('John Doe');
var jane = new User('Jane Dane');
jane.fullName = 'Jane Doe';
document.write(
'<pre>' + joe.firstName + '</pre>' +
'<pre>' + jane.lastName + '</pre>'
);
However, as noted in the code comments above you can't set a property on this to the same name as a defined property with a setter. For example:
// defining `firstName`
firstName: {
...
set: function(value) {
this.firstName = value; // NOTE: This will throw an error
}
This operation will cause a recursion stack error as it will continuously try to update firstName since this.firstName is a setter.
To avoid this you could use local scoped variables inside the constructor function and do something like:
function User(fullName) {
var firstName;
var lastName;
Object.defineProperties(this, {
firstName: {
get: function() {
return firstName;
},
set: function(value) {
return (firstName = value);
}
},
lastName: {
get: function() {
return lastName;
},
set: function(value) {
return (lastName = value);
}
},
fullName: {
get: function() {
return firstName + ' ' + lastName;
},
set: function(value) {
var names = value && value.split(' ');
firstName = names[0];
lastName = names[1];
}
}
});
if (fullName) {
this.fullName = fullName;
}
}
var joe = new User('John Doe');
var jane = new User('Jane Dane');
jane.lastName = 'Doe';
document.write(
'<pre>' + joe.firstName + '</pre>' +
'<pre>' + jane.lastName + '</pre>'
);
Some issues/changes needed to your code:
this.fullName.split(" ")[0]; => will try to invoke the getFullName since fullName is defined as a property. Since you have not defined getFullName this results in an error
Say you go ahead and define a getter for fullName:
get: function() {
return this.fullName;
}
This will throw a stackoverflow since this.fullName ends up recursively calling getFullName()
The right way to use it would be (of course update the setters to do something useful):
function User(fullName) {
this.fullName = fullName;
Object.defineProperties(this, {
firstName: {
get: function () {
return this.fullName.split(" ")[0];
},
set: function (value) {
this.firstName = value;
}
},
lastName: {
get: function () {
return this.fullName.split(" ")[1];
},
set: function (value) {
this.lastName = value;
}
}
});
}
var user = new User("New User");
alert( user.firstName );
fullName does not have a getter so it return undefined
get
A function which serves as a getter for the property, or undefined if there is no getter. The function return will be used as the value of property.
Defaults to undefined.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#Description
Finally i'm writing a question on my own because i read other question here but still don't understand why my code doesn't work. Perhaps someone can explain me what i got wrong?
The Code runs till the search for the name "Joe", Then it say par2 is not defined...Why? In the check after the search function i can clearly see that both parameters par1 and par2 are returned...
var friends = {};
friends.bill = {
firstName: "Bill",
lastName: "Gates",
number: "(206) 555-5555",
address: ['One Microsoft Way', 'Redmond', 'WA', '98052']
};
friends.steve = {
firstName: "Steve",
lastName: "Jobs",
number: "(408) 555-5555",
address: ['1 Infinite Loop', 'Cupertino', 'CA', '95014']
};
function list(obj) {
for (var prop in obj) {
console.log(prop);
}
};
function bettersearch(name2) {
var sna = name2
for (var prop in friends) {
if (friends[prop].firstName === name2) {
// console.log("Value found :",friends[prop]);
return {
par1: friends[prop],
par2: sna
}
}
}
};
// Test if the variables are returned
var test = bettersearch("Bill")
console.log("\n\n",test);
console.log("\n\n",test.par1);
console.log("\n\n",test.par2);
//Formatting function for a nice Output
function format(obj) {
if (obj) {
var result = "";
result += "\nName: " + obj.par1.firstName + " " + obj.lastName;
result += "\nNumber: " + obj.par1.number;
result += "\nAddress: " + obj.par1.address.join(', ');
console.log(result);
} else {
console.log("\nDer Name", obj.par2, "wurde nicht gefunden");
}
}
//Call the functions
format(bettersearch("Bill"));
format(bettersearch("Steve"));
format(bettersearch("Joe"));
Then it say par2 is not defined...
No, it doesn't. It says something like Cannot convert 'obj' to object or Cannot access 'par2' on undefined.
Why?
Because your bettersearch function does not return anything when it doesn't find the name. In your format function you explicitly check for the existence of obj, but despite it being undefined you try to access obj.par2.
I think you are looking for
function bettersearch(name) {
for (var prop in friends)
if (friends[prop].firstName === name)
return {
friend: friends[prop],
name: name
};
return {
name: name
}; // always return a result object
}
function format(obj) {
if (obj.friend) {
var result = "";
result += "\nName: " + obj.friend.firstName + " " + obj.friend.lastName;
result += "\nNumber: " + obj.friend.number;
result += "\nAddress: " + obj.friend.address.join(', ');
console.log(result);
} else {
console.log("\nDer Name", obj.name, "wurde nicht gefunden");
}
}
This might be a much better way to structure your data and write your search function
var friends = [
{
firstName: "Bill",
lastName: "Gates",
number: "(206) 555-5555",
address: ['One Microsoft Way', 'Redmond', 'WA', '98052']
},
{
firstName: "Steve",
lastName: "Jobs",
number: "(408) 555-5555",
address: ['1 Infinite Loop', 'Cupertino', 'CA', '95014']
}
];
function searchFriends(firstName) {
return friends.filter(function(f) {
return f.firstName === firstName;
});
}
console.log(searchFriends("Bill"));
//=> [{"firstName":"Bill","lastName":"Gates","number":"(206) 555-5555","address":["One Microsoft Way","Redmond","WA","98052"]}]
console.log(searchFriends("Steve"));
//=> [{"firstName":"Steve","lastName":"Jobs","number":"(408) 555-5555","address":["1 Infinite Loop","Cupertino","CA","95014"]}]
console.log(searchFriends("Joe"));
//=> []
I make this suggestion because in your code, it'd be very easily to have duplicates.
E.g., what about John Smith and John Smyth? Both would use friends.john...
If you want the search result to return the query and the matches
function searchFriends(firstName) {
return {
search: firstName,
result: friends.filter(function(f) {
return f.firstName === firstName;
})
};
}
Use it the same way
console.log(searchFriends("Steve"));
// {
// search: "Steve",
// result: [{"firstName":"Steve","lastName":"Jobs","number":"(408) 555-5555","address":["1 Infinite Loop","Cupertino","CA","95014"]}]
// }
console.log(searchFriends("Joe"));
// {
// search: "Joe",
// result: []
// }
The actual error is
"TypeError: Cannot read property 'par2' of undefined
Your error is in your console.log() line where if(obj) returns false (meaning there is no object - it's actually undefined):
console.log("\nDer Name", obj.par2, "wurde nicht gefunden");
Remove that line altogether.