I kind of know that we cannot observe properties of an object by simply observing an object. But I want to know if my understanding is correct.
Can we do something like this ? http://jsfiddle.net/Z3gNC/
function Person(name, age) {
this.name = name;
this.age = age;
}
$(function () {
var vm = (function () {
var person = ko.observable(new Person("ABC", 23));
return {
person: person
};
})();
ko.applyBindings(vm);
});
It is not working so we can't I guess. I also don't understand where this character 'c' comes from.
You're not far off, you just need to unwrap your person observable when referencing it in your markup:
Updated JSFiddle
<input data-bind="value:person().name" />
<input data-bind="value:person().age" />
Edit from comment
Update JSFiddle
You can make the properties of Person observable so that they track changes like so:
function Person(name, age) {
this.name = ko.observable(name);
this.age = ko.observable(age);
}
I just updated your fiddle to be the more-usual KO pattern:
http://jsfiddle.net/Z3gNC/1/
function Person(name, age) {
this.name = ko.observable(name);
this.age = ko.observable(age);
}
$(function () {
var vm = (function () {
var person = new Person("ABC", 23);
return {
person: person
};
})();
ko.applyBindings(vm);
});
The reason you see 'c' in your original fiddle is because vm.person is a ko.observable function, which when minimised looks like:
function c(){if(0<arguments.length)return c.Ka(d,arguments[0])&&(c.P(),d=arguments[0],c.O()),this;a.k.zb(c);return d}
Every function has a name property:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
so in this case vm.person.name is the name of the function vm.person which when minified is 'c' !
Edit: if you use a single observable Person, KO won't know that the inner property changes, unless you tell it with a valueHasMutated call. This next demo uses your VM structure and binds the changes in the textbox to the span, via a change event and a valueHasMutated call. So it works, but the 'pure' KO approach above is perhaps preferable for simplicity.
http://jsfiddle.net/Z3gNC/6/
function Person(name, age) {
this.name = name;
this.age = age;
}
$(function () {
var vm = (function () {
var person = ko.observable(new Person("ABC", 23));
var mutate = function(data, event) {
data.person.valueHasMutated();
}
return {
person: person,
mutate: mutate
};
})();
ko.applyBindings(vm);
});
... which needs this HTML:
<input data-bind="value:person().name, event: {change: mutate}" />
Related
var myProp = function() {
this.name = name;
this.gender = gender;
this.age = age;
}
So I have JS class with a bunch of properties. That look like that above.
$('#nav li').on('click', function() {
var selected_li = $(this);
function getProp() {
myProp = function() {
return this.name + 'John' + this.gender + 'Male' + this.age + 'Nine';
}
}
});
console.log(myProp);
onClick of my element, i'm trying to update the properties within myProp so if I do console.log() i'll get name = 'John', gender = 'male' and so on.
Is it something to do with the scope why I cannot update my properties of myProp?
Whenever I console log myProp I just get back myProp, exactly how it is without any properties being updated?
Still learning, apologies if this seems stupid.
Thanks.
In your first code block, you appear to have some global JS that sets a global variable (myProp) to a function.
In your second code block, you have an event handler which defines a locally scoped function declaration called myProp.
That function masks the global one for the lifetime of the call to the event handler.
You never call the locally scoped myProp, but if you did, it would immediately overwrite itself with a different function (defined with a function expression).
At no point do you ever touch the global myProp, and you never do anything with the local one.
It looks like you just want to have a global object with some properties in it. If you wanted to change the values of those properties you would do something like this:
var myProp = {
name: name,
gender: gender,
age: age,
}
$('#nav li').on('click', function() {
myProp.name = "John";
myProp.gender = "Male";
myProp.age = "Nine";
});
Assuming I've understood your question correctly, you can modify the property values of an instance of myProp:
// Create an instance of myProp
var myPropInstance = new myProp('name', 'gender', 'age');
$('#nav li').on('click', function() {
var selected_li = $(this);
// Update the property values of an instance of myProp
myPropInstance.name = 'new name';
});
Notice that I'm passing values into the myProp constructor... you'll probably want to update that constructor to set instance properties based on those:
var myProp = function(name, gender, age) {
this.name = name;
this.gender = gender;
this.age = age;
}
This is your constructor. It's the blueprints for making an object.
function Person(name, gender, age) {
this.name = name;
this.gender = gender;
this.age = age;
}
Creating a person
var John = new Person("John", "Male", "Nine");
Changing Johns gender:
John.gender = "Female"
create getter and setter like this
var myProp = function() {
this.name = "k"
var self = this
this.setName =function(name){
self.name = name
}
this.getName =function(){
return self.name
}
}
then use new to get its method
var myObject = new myProp();
myObject.getName()
myObject.setName("new name")
myObject.getName()
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);
$(document).ready(function () {
var patient = (function (options) {
var age = options.age;
var name = options.name;
function getName() {
return this.name;
}
function setName(val) {
name = val;
}
function getAge() {
return this.age;
}
function setAge(val) {
age = val;
}
return {
getAge: getAge,
setAge: setAge,
getName: getName,
setName: setName
}
})();
});
I realize that I'm never passing any options in my example here.
If I try to do something like patient.setAge('100') and then console.log(patient.getAge()) I get an error saying cannot read property Age of undefined. The overarching theme that I'm trying to get at is within a module, how can I emulate consturctors to instantiate a new patient object while keeping all the OOP goodness of private variables and all that jazz.
I've seen some examples of constructors in a module pattern on here and I haven't understood them very well. Is it a good idea in general to have a constructor in a module? Is its main purpose similarity with class-based languages?
This is a constructor:
function Patient(options) {
options = options || {};
this.age = options.age;
this.name = options.name;
}
$(document).ready(function () {
var patient = new Patient();
});
You can put it inside a module if you want. What you shouldn’t do is provide getters and setters, especially ones that don’t do anything. If you’re exposing a variable through two properties to get and set it, it should just be one property.
Try this
function Patient (options) {
options = options || {};
var age = options.age;
var name = options.name;
function getName() {
return name;
}
function setName(val) {
name = val;
}
function getAge() {
return age;
}
function setAge(val) {
age = val;
}
return {
getAge: getAge,
setAge: setAge,
getName: getName,
setName: setName
}
}); // pass empty object
$(document).ready(function () {
var p1 = new Patient({});
var p2 = new Patient();
var p3 = new Patient({age:20});
var p4 = new Patient({name:"abcd"});
var p5 = new Patient({age:21, name:"abcd"});
});
I'm looking for the most optimized way to have an object in JS; since JS allows you to do something in multiple ways I want to know which is considered to be "best practice".
A conceptual use of the object would be this:
var John = new Person('John');
var Foo = new Person('Foo');
console.log(John.getName()); //Return 'John'
console.log(Foo.getName()); //Return 'Foo'
console.log(John.name); //undefined
console.log(Foo.name); //undefined
I have some examples here:
Example #1:
var Person = function (name) {
this.getName = function () { return name; }
}
Here I actually have no properties; "name" cannot be changed or be read by public and getName method can be accessed public and invoke with local name variable. This actually meets my needs.
Example #2:
function Person (name) {
this.getName = function () { return name; }
}
This has same behaviour as example #1. I'm just not sure about the difference between var method = function () {}; and function method() {}; from a functional and performance perspective.
Example #3:
var Person = function (name) {
this.name = name;
Person.prototype.getName = function () { return this.name; }
}
Here I have name property which can be read/write by public and I also have a prototype getName method that can be accessed public.
Example #4:
var Person = function (name) {
this.name = name;
if (!Person._prototyped) {
Person.prototype.getName = function () { return this.name; }
Person._prototyped = true;
}
}
Here I have what I had in example #3 with the difference that I make sure that prototype methods are set only once and only when required.
So the end question is, which of those you will suggest me to follow or if any of them then which way is the best practice?
For what you want, the best way is probably this:
/**
* #constructor
*/
function Person(name) {
this.getName = function() {
return name;
};
}
Why is this? Well, first of all, encapsulation. If possible, you generally want to put the function in the prototype, like so:
/**
* #constructor
*/
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
};
However! In this case, it appears you don't want Person.name to be accessible. For that reason, you need to use closures.
As for this method:
var Person = function (name) {
this.name = name;
Person.prototype.getName = function () { return this.name; }
}
That's not good. You publicly expose this.name, so it offers no advantage over the previous prototype method, but you continually overwrite Person.prototype.getName with the same function. There's no point in doing that; this will be the appropriate object every time. What's more, Person.prototype.getName won't be accessible until the first Person object is instantiated so there's not much point in making it "public" in the first place. Your fourth example is basically identical, with more cruft making it harder to understand, but it still has all the disadvantages.
So, in this case, go with the first version; when possible, though, set methods on prototype so they can be called outside of an instance.
Finally, I would recommend using:
function Person() {
}
over
var Person = function() {
}
because 1) The second example is missing a semicolon, 2) the var implies that the constructor is variable which it should not be, and 3) I don't believe JDoc allows #constructor to be applied to it, causing a warning in Closure Compiler at least1.
1 Okay, not so important. But still...
In example 3 and 4 it should be:
var Person = function (name) {
this.name = name;
};
Person.prototype.getName = function () { return this.name; }
And:
var Person = function (name) {
this.name = name;
};
if (!Person._prototyped) {
Person.prototype.getName = function () { return this.name; }
Person._prototyped = true;
}
As you don't need to mess with the prototype each time you call the constructor.
Not sure which is fastest (as they are all valid for your purposes), which is what your asking, but I wouldn't worry as this seems like micro-optimizing. If you must know then you can use a site like http://jsperf.com/
The fastest way I can imagine would be :
function Person(name) {
this.getName = function() {
return name;
};
}
As minitech said. The reason is as follows:
Each time the js engine has to go "up" the prototype chain it takes away a fraction of a ms (or fraction of a sec on IE :) ), and as declaring variables can take up time (also negligible) you avoid doing that too. Hope that helps
Works well on node.js. AFAIK, arguments are mutable. Closures will remember values. Hence this will work. I guess this solves it all.
var Person = function(Name) {
this.getName = function(){return Name;}
this.setName = function(newName) { Name = newName; }
},
me = new Person('John');
console.log(me.getName());
me.setName('Peter');
console.log(me.getName());
I have an object written like this:
Object1.prototype = {
isInit: false,
Get : function (){}
}
Now I'd like to add a constructor which takes one parameter. How can I do it?
Class declaration
var User = function(name, age) { // constructor
}
User.prototype = {}
Instance variables (members)
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype = {}
Static variables
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype = {
staticVar: 15,
anotherStaticVar: 'text'
}
Here I defined two static variables. Each User instance has access to these two variables. Note, that we can initialize it with value;
Instance functions (methods)
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype = {
getName: function() {
return this.name;
},
setName: function(name) {
this.name = name;
}
}
Usage example:
var user = new User('Mike', 29);
user.setName('John');
alert(user.getName()); //should be 'John'
Static functions
var User = function(name, age) {
this.name = name;
this.age = age;
}
User.create = function(name, age) {
return new User(name, age);
}
User.prototype = {}
Assuming that by "ctor" you mean "constructor", in JavaScript that's just a function. In this case your constructor would need to be "Object1" itself - in other words, what you've got there makes sense if you have already defined "Object1" to be a function.
Thus,
function Object1(param) {
// constructor code
}
would be the constructor for your type.
Now there are some JavaScript libraries that provide a utility layer for defining classes. With those, you generally pass some sort of object (like you've got) that includes an "init" function. The libraries provide APIs for creating "classes" and for extending one class from another.
Javascript has prototype based object model. Check this mozilla wiki page and suddenly you'll feel much better in js land.
We can define a constructor in javaScript is same as we fine function, so constructor is just a function.
//function declaration
function func(){}
In case of Contructor We use initial letter in caps in construct like
//constructor
function Func(){}
now do whatever you want to with your constructor
var constructor1 = new Func();
class CLASS_NAME
{
private:
int variable;
public:
CLASS_NAME() //constructor
{
variable = 0;
}
};