javascript: Define reference in nested object to parent object - javascript

I have following object:
var myObject = {
attributes: { name: "dev.pus", age: 29 },
someInjectedObject: {
name: "someComponent",
action: function() {
// do something
return this.this.attributes.name; // this surely won't work :(
}
}
};
As you see I want to get myObject.attributes.name from an nested part of the object without having to observe the value.
How do I do this? How do I define a reference?
EDIT:
A simple myObject.attributes isn't enough because myObject changes or better gets assigned to a new variable.

Create a closure around your object:
var myObject = (function() {
var result = {
attributes: { name: "dev.pus", age: 29 },
someInjectedObject: {
name: "someComponent",
action: function() {
// do something
return result.attributes.name;
}
};
};
return result;
})();

You can do refer to myObject directly like this:
var myObject = {
attributes: { name: "dev.pus", age: 29 },
someInjectedObject: {
name: "someComponent",
action: function() {
// do something
return myObject.attributes.name; // this surely will work :(
}
}
};
alert(myObject.someInjectedObject.action());
​
DEMO
​

Related

Simple JS example of Singleton Pattern not working

I made a simple example of Singleton Pattern but it is giving blank objects in both cases. Please someone help?
var a = ( function(){
var instance = {};
function init() {
return {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
}
return {
getInstance: function(){
if(!instance) {instance = init();}
return instance;
}
}
})();
console.log(a.getInstance());
console.log(a.getInstance());
As I said in a comment, the problem is that instance is initialized to {}, which is truthy, so !instance will never be true.
There's only one instance variable, created for the one call to your anonymous function. That's the whole point of having it, it tracks the singleton. So initialize it with a falsy value (or leave it with the default undefined, which is falsy):
var a = ( function(){
var instance = null;
function init() {
return {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
}
return {
getInstance: function(){
if(!instance) {instance = init();}
return instance;
}
}
})();
const first = a.getInstance();
console.log(first);
const second = a.getInstance();
console.log(second);
console.log(first === second); // true
.as-console-wrapper {
max-height: 100% !important;
}
That said, you only need all of this complexity if you want late initialization. Otherwise, just create the object:
var a = {
instance = {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
};
Then a.instance is the singleton. If you want it to be non-writable:
var a = Object.defineProperty({}, "instance", {
value: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
});
(That will also be non-enumerable. If you want it to be enumerable, add enumerable: true.)
Or just:
var instance: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
If you want that to be read-only, use const in any modern environment:
const instance: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
In all of the above, remember that although you may have a singleton, and although the instance property/constant may be read-only, nothing about the object itself is immutable. Properties can be added, removed, changed, etc. To prevent that, use Object.freeze.
If in case this can be a variety to T.J. Crowder answer, You may create an instance once and save it to a variable, then every time the method is called, you may return that variable. I think closure plays a role here.
var a = ( function(){
var instance = {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
return {
getInstance: function(){
return instance;
}
}
})();
let b = a.getInstance();
let c = a.getInstance();
console.log(b);
console.log(c);
console.log( b === c )

How to pass argument in javascript

var Person = {
name: "jana",
getName: function(callBack) {
callBack();
console.log("** "+this.name);
}
}
var anotherPerson = { name: "prabu"}
I have 2 objects. I need "anotherPerson" to be bound with the Person object. Also, I want to send parameter as a function.
I have tried below methods, but its not working
Person.getName.apply(anotherPerson, function(){})
Person.getName.apply(anotherPerson)(function(){})
Use call to pass an arbitrary number of arguments to your function, or apply to pass an array of arguments:
var Person = {
name: "jana",
getName: function(callBack) {
callBack();
console.log("** " + this.name);
}
}
var anotherPerson = {
name: "prabu"
}
Person.getName.call(anotherPerson, function () {})
Person.getName.apply(anotherPerson, [function () {}])
Have you tried Object.assign ? Like so
var Person = {
name: "jana",
getName: function(callBack) {
callBack();
console.log("** " + this.name);
}
}
var anotherPerson = {
name: "prabu"
}
Object.assign(Person, anotherPerson).getName(alert)
You can use arrow function and return the name parameter to assign value to getName.
var Person = {
name: "jana",
getName: (obj) =>obj.name
}
var anotherPerson = {
name: "prabu"
}
Person.getName(anotherPerson);
console.log(Person);

Find duplicate object from one collection to another collection - using 2 arrays in knockout JS

In knockout JS I want to find out 1st duplicate object from my collection and return that object as modal. I have to check for 1st duplicate object from first array aginst 2nd Array based on my condition. Tried _findWhere & _.Some & _.each nothing worked. Can someone help
Here -- MyMainModal is my Moda which will have multiple objects
self.dupRecord= function (MyMainModal) {
var Modaldata= ko.mapping.toJS(MyMainModal);
return _.some(Modaldata, function (MD1) {
return _.some(Modaldata, function (MD2) {
if ((MD1.ID!== MD2.Id) &&
(MD1.Name === MD2.name));
});
});
};
How about incorporating the check for first duplicate into the mapping? Something like:
function Child(data) {
ko.mapping.fromJS(data, {}, this);
};
var model = {
children: [{
id: '1',
name: 'Billy'
}, {
id: '2',
name: 'Susy'
}]
};
var mapping = {
children: {
key: function(data) {
return ko.utils.unwrapObservable(data.id);
},
create: function(options) {
console.log('creating ' + options.data.name, options.parent);
var newChild = new Child(options.data);
if(options.parent.firstDuplicate() === undefined)
options.parent.children().forEach(function(child) {
if(child.name() === newChild.name())
options.parent.firstDuplicate([child, newChild]);
});
return newChild;
},
update: function(options) {
console.log(' updating ' + options.data.name);
return options.target;
}
}
};
var vm = {
children: ko.observableArray(),
firstDuplicate: ko.observable()
};
ko.mapping.fromJS(model, mapping, vm);
ko.applyBindings(vm);
model.children.push({
id: 3,
name: 'Billy'
});
setTimeout(function() {
console.log('--remapping--');
ko.mapping.fromJS(model, mapping, vm);
}, 2000);
I read that as, "if we're not updating the record, potentially set the first duplicate." Here's a fiddle: http://jsfiddle.net/ge1abt6a/

What's the syntax to add a function other than an accessor?

I'm learning the JavaScript with Node. I like the idea of creating objects with factories, and after reading a lot on this subject, I chose to create objects with this code:
// ES6 only
'use strict';
// The base object, "object literal" syntax
let animal2 = {
// public member
animalType: 'animal',
// public method
describe() {
return `This is "${this.animalType}"`;
}
};
// factory function which serves 2 purposes:
// - encapsulation, that's where private things are declared thanks to closures
// - the "real" object creation, this prevents to use "new" which is not really Js-ish
let afc = function afc() {
// private member
let priv = "secret from afc";
return Object.create(animal2, {
// Object customisation
animalType: { value: 'animal with create'},
// object extension. The new objects created here get 3 new members:
// - a private member
// - a new property
// - a new method to access the private member
// new public member
color: { value: 'green' },
secret: {
get: function () { return priv; },
set: function (value) { priv = value; },
},
KO1() {
console.log("KO1");
},
KO2: function() {
console.log("KO2");
}
});
}
// creation of an animal instance
let tac = afc();
My problem is I can't figure out what's the syntax to add a function which can manipulate private data while not being just an accessor. I put here 2 examples which came to my mind (KOx), but as their names suggest, this syntax leads to: "KOx is not a function".
Object.create expects an object of property descriptors as its second argument. This is why you have to use {value: …} or {set: …, get: …} everywhere.
And in fact you'd have to do the same for a method - which is just a standard property with a function as its value:
…
KO3: {value: function() {
…
}},
…
However, I'd avoid using property descriptors when you don't need them. Object.assign is a better fit:
return Object.assign(Object.create(animal2, {
secret: {
get() { return priv; },
set(value) { priv = value; },
}
}), {
animalType: 'animal with create',
color: 'green',
KO1() {
console.log("KO1");
},
KO2: function() {
console.log("KO2");
}
});
Why don't just use the getter syntax?
return {
__proto__: animal2, // To be honest __proto__ is not a good thing to use
animalType: 'animal with create',
color: 'green',
get secret() { return priv; },
set secret(value) { priv = value; },
get KO3() { console.log("KO3"); },
// or just the following, if you would like it to be a regular member function
// KO3() { console.log("KO3"); },
};
Or without explicit __proto__:
const result = {
animalType: 'animal with create',
color: 'green',
get secret() { return priv; },
set secret(value) { priv = value; },
get KO3() { console.log("KO3"); },
};
Object.setPrototypeOf(result, animal2);
return result;

Jasmine test complaining about 'undefined' is not an object

I have checked other questions similar to my problem. but this problem can apparently be different in every case.
Angular Jasmine Test complains
TypeError: 'undefined' is not an object (evaluating 'fields.forEach')at discoverDependentFields
Here is my discoverDependentFields function
discoverDependentFields($scope.response.Fields);
function discoverDependentFields(fields) {
fields.forEach(function (field) {
field.DependencyFieldEvaluated = '';
if (field.DependencyField) {
var foundFields = fields.filter(function (fieldToFind) { return fieldToFind.Name === field.DependencyField; });
if (foundFields.length === 1) {
field.DependencyFieldEvaluated = foundFields[0];
}
}
});
}
and in the test I have this bit
this.controller('MyController', {
'$scope': this.scope,
}
});
this.scope.response.Fields = [
{
Name: "UserIdentity",
Value: {
"FirstName": "John"
},
PropertyName: "User.Identity"
}
];
I use the value of field.DependencyFieldEvaluated in a function in a directive like this
function dependencyMet(field) {
var dependentField = field.DependencyFieldEvaluated;
var met = compareToDependencyValue(field, dependentField.Value);
return met;
}
I have no idea why it is complaining
If
discoverDependentFields($scope.response.Fields);
is a line in your controller, then you need to setup the $scope.response.Fields data before instantiating the controller. In other words, swap the order of operations in your test to be
this.scope = {};
// or maybe this.scope = $rootScope.$new()
this.scope.response = {
Fields: [{
Name: "UserIdentity",
Value: {
FirstName: "John"
},
PropertyName: "User.Identity"
}]
};
this.controller('MyController', {
$scope: this.scope,
});

Categories