How do I construct a new instance of a defined object?
I have code similar to this but the this.User = new User(); it doesn't work.
(function () {
SomeApp = {
User: {
FirstName: '',
LastName: ''
},
Users: [],
init: function () {
this.User.FirstName = 'Joe';
this.User.LastName = 'Blogs';
//add user to list
var copiedUser = {};
$.extend(copiedUser, this.User);
this.Users.push(copiedUser);
//create new user
this.User = new User();
this.User.FirstName = 'Jane';
//add user to list
var copiedUser = {};
$.extend(copiedUser, this.User);
this.Users.push(copiedUser);
}
}
SomeApp.init();
})();
If you want to be able to create object using new, you may create a "constructor" :
function User() {
this.FirstName = '';
this.LastName = '';
}
Side note : I'd recommend you to follow best practices in naming variables. Please read this guide.
Related
I want to add functions to JSON Objects, but I can't find function for assigning to all objects, only to one.
This code works with Arrays:
Object.defineProperty(Array.prototype, 'random', {
value: () => {
return this[Math.floor(Math.random() * this.length)];
},
});
I've also found this code:
const obj = {name: 'Bob'};
obj.fullName = function() { return this.name }
But that one only works for specific object, not all of them.
Is it event possible to write global functions for all JSON Objects, and if is, then how to do it?
You could add the function to Object.prototype. Note that this is not considered a very good practice because it could impact the rest of the code (like shown in the comments):
Object.prototype.fullName = function() { return this.name; };
const obj = { name: 'Bob' };
console.log(obj.fullName());
You should consider doing this instead:
const baseObject = { fullName: function() { return this.name; } };
const obj = Object.create(baseObject, { name: { value: 'Bob', writable: true } });
console.log(obj.fullName());
And if your target runtime (browser?) supports ECMAScript 6, you could also create a dedicated class for this:
class MyClass {
constructor(name) {
this.name = name;
}
fullName() { return this.name; }
}
const bob = new MyClass('Bob');
console.log(bob.fullName());
Finally, the class syntax for ECMAScript 5:
function MyClass(name) {
this.name = name;
}
MyClass.prototype.fullName = function() { return this.name; }
const bob = new MyClass('Bob');
console.log(bob.fullName());
I am trying to achieve knockout observe computed behavior in vanila js
In react, you will have both these variables on state and compute the fullname
How can we achieve the same in vanila js
function person(firstname,lastname) {
this.firstname = firstname;
this.lastname = lastname;
this.fullName = `${this.firstname}${this.lastname}`
}
var person1 =new person("abc","k");
Object.defineProperty(person,'firstname',{
get: () => {
return person1['firstname'];
},
set: (name) => {
person1['firstname'] = name;
}
});
Object.defineProperty(person,'lastname',{
get: () => {
return person1['lastname'];
},
set: (name) => {
person1['lastname'] = name;
}
});
Object.defineProperty(person,'fullName',{
get: () => {
return `${person1['firstname']}-${person1['lastname']}`;
}
});
console.log(person1.firstname, "firstnmae");
person1.firstname ="sah";
console.log(person1.lastname, "lastname");
console.log(person1.fullName, "fullname");
Look at this code:
var person = {
firstname: 'abc',
lastname: 'k'
};
Object.defineProperty(person,'fullName',{
get: function() {
return `${this['firstname']}-${this['lastname']}`;
}
});
var person1 = Object.create( person );
console.log(person1.firstname, "firstnmae");
person1.firstname ="sah";
console.log(person1.lastname, "lastname");
console.log(person1.fullName, "fullname");
there's no need defining firstname and lastname by .defineProperty because those setter and getter will work by default as you wrote them.
you should use this syntax, as it's easier to read/maintain afterward, otherwise, if you would like to stick to that constructor syntax, here you go:
var person = function() {};
Object.defineProperty(person,'firstname',{
value: 'abc',
writable: true
});
Object.defineProperty(person,'lastname',{
value: 'k',
writable: true
});
Object.defineProperty(person,'fullName',{
get: function() {
return `${this['firstname']}-${this['lastname']}`;
}
});
var person1 = Object.create( person );
console.log(person1.firstname, "firstnmae");
person1.firstname ="sah";
console.log(person1.lastname, "lastname");
console.log(person1.fullName, "fullname");
I think you need more investigation about Object.create() and MDN is the best place.
arrow-functions have lexical this, be careful!
this syntax maybe clarifies some points about Object.create() for you:
var person = function() {};
person.prototype.firstname = 'abc';
person.prototype.lastname = 'k';
Object.defineProperty(person.prototype,'fullName',{
get: function() {
return `${this['firstname']}-${this['lastname']}`;
}
});
var person1 = Object.create( person.prototype );
console.log(person1.firstname, "firstnmae");
person1.firstname ="sah";
console.log(person1.lastname, "lastname");
console.log(person1.fullName, "fullname");
I have two different components that leverage the same AuthStore, FacebookUser and Quiz.
The FacebookUser component updates the AuthStore by executing the login action and that actions causes it to execute emitChange. However, the onChange handler for the Quiz does not fire.
AuthStore.js
console.log("AuthStore::CREATED");
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var AuthConstants = require('../constants/AuthConstants');
var assign = require('object-assign');
var CHANGE_EVENT = 'change';
var _user = undefined;
var AuthStore = assign({}, EventEmitter.prototype, {
isLoggedIn: function() {
return _user !== undefined;
},
getUser: function() {
return _user;
},
emitChange: function() {
console.log('AuthStore::emitChange');
this.emit(CHANGE_EVENT);
},
addChangeListener: function(callback) {
console.log('AuthStore::addChangeListener', callback);
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
}
});
// Register callback to handle all updates
AuthStore.dispatchToken = AppDispatcher.register(function(action) {
console.log('AuthStore::action', action);
switch(action.actionType) {
case AuthConstants.AUTH_LOGIN:
_user = action.user;
AuthStore.emitChange();
break;
case AuthConstants.AUTH_LOGOUT:
_user = undefined;
AuthStore.emitChange();
break;
default:
// no op
}
});
module.exports = AuthStore;
FacebookUser.jsx
var AuthActions = require('../../actions/AuthActions');
var AuthStore = require('../../stores/AuthStore');
function componentWillMount() {
AuthStore.addChangeListener(this.onChange);
}
function onChange() {
console.log('FacebookUser::onChange');
var user = AuthStore.getUser();
this.setState(user);
}
function populateUserProfile(userId) {
FB.api('/' + userId, {fields: 'email,name'}, function(response) {
console.log('FacebookUser::populateUserProfile', response);
AuthActions.login(response);
}.bind(this));
}
Quiz.jsx
var AuthStore = require('../../stores/AuthStore');
var QuizStore = require('../../stores/QuizStore');
function componentWillMount() {
AuthStore.addChangeListener(this.onChange);
QuizStore.addChangeListener(this.onChange);
}
function onChange() {
console.log('Quiz::onChange');
var quiz = QuizStore.getQuiz();
if (!quiz.person.email) {
var user = AuthStore.getUser();
quiz.person.email = user.email;
}
this.setState(quiz);
}
AppDispatcher.js
var Dispatcher = require('flux').Dispatcher;
module.exports = new Dispatcher();
I thought that the stores were Singleton's, however, it appears that's not the case. I know I'm missing something stupid. Looking forward to the answer!
Console Output
Below you can see that the FacebookUser::onChange fires. I'm pretty sure the issue is that the AuthStore is created for both components. That's pretty visible from the AuthStore::CREATED log.
AuthStore::CREATED
QuizStore::create
AuthStore::addChangeListener onChange() {
console.log('Quiz::onChange');
var quiz = QuizStore.getQuiz();
if (!quiz.person.email) {
var user = AuthStore.getUser();
quiz.person.email = user.email;
}
th…
QuizStore::addChangeListener onChange() {
console.log('Quiz::onChange');
var quiz = QuizStore.getQuiz();
if (!quiz.person.email) {
var user = AuthStore.getUser();
quiz.person.email = user.email;
}
th…
AuthStore::CREATED
AuthStore::addChangeListener onChange() {
console.log('FacebookUser::onChange');
var user = AuthStore.getUser();
this.setState(user);
}
FacebookUser::statusChangeCallback Object {authResponse: Object, status: "connected"}
FacebookUser::populateUserProfile Object {email: "mperren#gmail.com", name: "Michael Perrenoud", id: "10209047315608853"}
AuthActions::login
AuthStore::action Object {actionType: "AUTH_LOGIN", user: Object}
AuthStore::emitChange
FacebookUser::onChange
Rather than exposing the constructor expose an instance call new on your stores and expose that instance. That way it will be a singleton, in tests I expose a non default export so I can reinititialse a store for each test.
So the issue ended up being a bit esoteric. I was including this user component with a different ReactDOM renderer. Effectively like its own application. This is what was causing the problem. Because they were in different scopes they didn't share the same stores. Moving the component to being rendered by the root component for the application fixed it.
The code below will create a Email Activity in CRM but I can't figure out how to add multiple recipients. If I try to add a second recipient it just replaces the first recipient.
function CreateEmail() {
alert("CreateEmail Begin");
var email = new Object();
email.Subject = "Sample Email Using REST";
SDK.JScriptRESTDataOperations.Create(email, "Email", EmailCallBack, function (error) { alert(error.message); });
}
// Email Call Back function
function EmailCallBack(result)
{
var activityParty=new Object();
// Set the "party" of the ActivityParty // EntityReference of an entity this activityparty relatated to.
activityParty.PartyId = {
Id: "8384E684-7686-E011-8AF0-00155D32042E",//replace this with the contactid from your system.
LogicalName: "contact"
};
// Set the "activity" of the ActivityParty
// EntityReference.
activityParty.ActivityId = {
Id: result.ActivityId,
LogicalName: "email"
};
// Set the participation type (what role the party has on the activity).
activityParty.ParticipationTypeMask = { Value: 2 }; // 2 mean ToRecipients
SDK.JScriptRESTDataOperations.Create(activityParty, "ActivityParty",ActivityPartyCallBack , function (error) { alert(error.message); });
}
function ActivityPartyCallBack(reuslt)
{
alert("Process Completed");
}
Here’s a snippet that creates a email with multiple Recipients. The key was to set the email_activity_parties attribute so that we can pass an object.
Essentially email_activity_parties lets us submit a Array of Object instead a top level Object.
function CreateEmail() {
debugger;
var email = new Object();
email.Subject = "my email";
email.Description = "my email description";
var activityParties = new Array();
var partyObj0 = new Object();
partyObj0.PartyId = { Id: "a9568879-e61c-e411-80bb-000c29c1100f", LogicalName: "systemuser" };
partyObj0.ParticipationTypeMask = { Value: 1 };
activityParties[0] = partyObj0;
var partyObj1 = new Object();
partyObj1.PartyId = { Id: "b23f7a24-2223-e411-80c8-000c29c1100f", LogicalName: "contact" };
partyObj1.ParticipationTypeMask = { Value: 2 };
activityParties[1] = partyObj1;
var partyObj2 = new Object();
partyObj2.PartyId = { Id: "ffd09f25-1748-e411-80cb-000c29c1100f", LogicalName: "contact" };
partyObj2.ParticipationTypeMask = { Value: 2 };
activityParties[2] = partyObj2;
//set email.email_activity_parties to activityParties
email.email_activity_parties = activityParties;
SDK.REST.createRecord(email, "Email", EmailCallBack, function (error) { alert(error.message); });
}
// Email Call Back function
function EmailCallBack(result) {
debugger;
}
Dont have a REST sample I'm afraid, but in C# SOAP you have to pass a collection of entities, perhaps its the same in REST?
Entity e = new Entity("phonecall");
e["to"] = new Entity[]
{
ToActivityParty(new EntityReference("contact", contact1)),
ToActivityParty(new EntityReference("contact", contact2)),
};
static Entity ToActivityParty(EntityReference entityReference)
{
Entity party = new Entity("activityparty");
party["partyid"] = entityReference;
return party;
}
I'd like to create a Javascript object that can save and load its state (to local storage).
This is the basic pattern I'm using:
var obj = function () {
// private members
//
return {
// public members
load: function () {
this.state = JSON.parse(localStorage.getItem('obj'));
if (this.state === null) {
this.state = {
name: 'foo'
};
}
},
save: function () {
localStorage.setItem('obj', JSON.stringify(this.state));
}
};
}();
// load state
obj.load();
console.log(obj.state.name);
// save state
obj.state.name = 'bar';
obj.save();
But there's one thing that annoys me about this pattern: I have to access the object's persistent properties through the 'state' property.
How can I rewrite this so I can use the object in a more natural way, like:
// load state
obj.load();
console.log(obj.name);
// save state
obj.name = 'bar';
obj.save();
This is a very simple 'state', but the solution has to work for a complex state object with nested objects, arrays etc., so simply adding a 'name' property to my object is not what I'm after.
If you don't care which properties get loaded/saved then you can simply copy all from state into self. For example, after reading into var state (instead of this.state since you don't want state to be a part of this anymore): for(x in state) this[x] = state[x];
similarly, you'd save out: var state = {}; for(x in this) state[x] = this[x]
However, if you want to have a pre-defined list, then I'd recommend: var fields = ['name', 'zip', 'age'];
And then use for(x in fields) this[x] = state[x] to load and for(x in fields) state[x] = this[x]; to save.
Sorry it's a bit pieced together, but I hope you can follow what I mean :)
EDIT: Added full example per OPs request.
An example of a full solution using this technique is as follows:
var obj = function () {
// private members
//
return {
// public members
load: function () {
var state = JSON.parse(localStorage.getItem('obj'));
if(state == null) state = { name: 'foo' };
for(x in state) this[x] = state[x];
},
save: function ()
{
var state = {};
// check if it's a function. This version taken from underscorejs
var isFunction = function(obj) {
return !!(obj && obj.constructor && obj.call && obj.apply);
};
for(x in this)
{
if(isFunction(this[x])) continue; // skip functions
state[x] = this[x];
}
localStorage.setItem('obj', JSON.stringify(state));
}
};
};
You can also accomplish a direct save when a property changes,
by using ES5 getters/setters or by using Watch.js
Watch.js example:
var obj = (function () {
// private members
//
var self = {
// Some properties
name: '',
otherName: '',
// Try to load state or use "foo state"
state: JSON.parse(localStorage.getItem('obj')) || {
name: 'foo'
},
save: function () {
localStorage.setItem('obj', JSON.stringify(this.state));
}
};
// Watch the object and save it to local storage, when a property changes
// (Of course, you don't need to call the save method here...)
watch(self, function(property, value) {
console.log('saving state!');
self.state[property] = value;
self.save();
});
return self;
}());
// Update some properties and see that it is saved to local storage.
obj.name = "Some name";
obj.otherName = "Some other name";
console.log(JSON.parse(localStorage.getItem('obj')));
Example on JsFiddle.
You could make the state internal and surface getters and setters:
var obj = function () {
// private members
var state = {};
return {
// public members
load: function () {
var loadedState = JSON.parse(localStorage.getItem('obj'));
if (loadedState === null) {
state = {
name: 'foo'
};
} else {
state = loadedState;
}
},
save: function () {
localStorage.setItem('obj', JSON.stringify(state));
},
getState: function (key) {
return state[key];
},
setState: function (key, value) {
state[key] = value;
}
};
};
Using jQuery's extend():
var obj = (function () {
return {
load: function () {
var stored = localStorage.getItem("obj");
var state = stored ? JSON.parse(stored) : {
name: 'foo'
};
$.extend(this, state);
},
save: function () {
localStorage.setItem("obj", JSON.stringify(this));
}
};
})();
// load state
obj.load();
console.log(obj);
// save state
obj.name = 'bar';
obj.save();
jsfiddle
All credit to pimvdb.