Example code:
var someVar = {};
someVar.text = "some text";
var thisFunc = function(){
this.subfunc = function(){
}
}
How can I assign thisFunc to someVar? If I do someVar = new thisFunc(), someVar.text will be gone.
Thank you.
I think you want something like bellow:-
var someVar = {};
someVar.text = "some text";
var thisFunc = function(){
//do some
}
someVar.func = thisFunc;
It seems that an extend function would come in handy in your situation. It's a little helper function, that assigns properties of one object to another one (if you are using a third party library like Underscore, you might already have such a function available):
function extend(obj1, obj2) {
for (var key in obj2) {
if (Object.prototype.hasOwnProperty.call(obj2, key)) {
obj1[key] = obj2[key];
}
}
return obj1;
}
Then you can do:
var someVar = {};
someVar.text = "some text";
var thisFunc = function(){
this.subfunc = function(){
}
}
someVar = extend(thisFunc, someVar);
Related
I want to copy the functions and properties of an object into new object. The old object should not effect by changing made in new Object.
Here is the object definition:
var Call = function() {
this.number="123";
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
I can access function1 using callobj.function1().
What I have tried to copy it:
Javascript:
var newcallobj = Object.assign({}, callobj);
In this case, i am not able to access function1 but i can access number property directly.
JQUERY:
var newObj = jQuery.extend(true, {}, callobj); OR
var newObj = jQuery.extend({}, callobj);
In this case, i am able to access function1 and property but when i change number like that newObj.number="222". It also change the value of original object.
I know that there is couple of other posts. But all is not working for me. Please let me know if i am doing any thing wrong?
AFTER #gurvinder372 answer(I am updating question):
After #gurvinder372 answer. It is working for first level of property but if it has another object like i show below and i change the value of property of another object. Then it is effecting on original object also.
var ABC = function(){
this.number = "333";
}
var Call = function() {
this.number="123";
this.anotherobj = new ABC();
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
newcallobj.anotherobj.number= "123";
console.log(newcallobj.anotherobj.number);
console.log(callobj.anotherobj.number);
Output of both is 123. #gurvinder372. can you check th above code ?
Object.assign only copies the enumerable properties of an object.
Use Object.create instead of Object.assign
var newcallobj = Object.create(callobj);
var Call = function() {
this.number="123";
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
console.log(newcallobj.function1());
Ok. By the help of #gurvinder372. The following solution is working for me.
var ABC = function(){
this.number = "333";
}
var Call = function() {
this.number="123";
this.anotherobj = new ABC();
}
Call.prototype.function1 = function() {
return this.number;
}
var callobj = new Call();
var newcallobj = Object.create(callobj);
newcallobj.anotherobj = Object.create(callobj.anotherobj);
newcallobj.anotherobj.number= "123";
console.log(newcallobj.anotherobj.number);
console.log(callobj.anotherobj.number);
Please let me know if there is any better solution other than this?
I am trying to sort an array using an onclick function, and I'm getting the error obj is not defined. Maybe it's not within the scope?
js file:
function pageLoad() {
var url = API_URL + "/api/Ticket/GetTickets";
var data = Ajax.getData(url);
var obj = [];
var tickets = JSON.parse(data.JsonResult);
obj.Tickets = tickets;
Tickets.Data = obj;
var viewModel = {
theObject: [obj.Tickets]
};
ko.applyBindings(viewModel);
}
function SortColumn(column) {
obj.Tickets.column.sort();
}
Yes, it is a scoping issue. Move your obj declaration outside the functions, that way it will be visible to both.
Something like this:
var obj = []; // <-- move here
function pageLoad() {
var url = API_URL + "/api/Ticket/GetTickets";
var data = Ajax.getData(url);
var tickets = JSON.parse(data.JsonResult);
obj.Tickets = tickets;
Tickets.Data = obj;
var viewModel = {
theObject: [obj.Tickets]
};
ko.applyBindings(viewModel);
}
function SortColumn(column) {
obj.Tickets.column.sort();
}
EDIT:
I'm not sure if you're aware, but [] is shorthand for an Array. If what you're trying to create is an Object, then you should change your assignment to var obj = {};
Of course obj is not within scope. It's not in global scope and you aren't passing it into the function.
you can use #smaili's answer as a fix or you can pass obj to the function.
function sortColumn(obj, column) {
obj.Tickets.column.sort();
return obj;
}
Then you'll call it with both arguments.
var sortedObj = sortColumn(obj, column);
Further explanation of scoping in Javascript
Let's say I have a function like the one below that creates a very simple micro-library:
var microLib = function(selector) {
var el;
var selectorEngine = function(selector)
{
var selector_value = selector.slice(1);
return document.getElementById(selector_value);
};
el = selectorEngine(selector);
Element.prototype.func_1 = function(){
return 'first';
};
Element.prototype.func_2 = function(){
return 'second';
};
return el;
};
window._$ = microLib;
This script will allow me to write code like this:
var elem = _$("#div_with_id"); //some element on my web page
console.log(elem.func_2()); //outputs 'second' in the console
So now, I'm looking for a way to extend _$ in a supplementary piece of code to add additional Element.prototype methods, which will allow me to write:
console.log(elem.func_3()); //to output 'third' in the console
The reason I need to do this is because this extension needs to take place in another JavaScript file, otherwise I would I have just added another method and be done with it.
How can I do this?
Here's an example of the approach that I am suggesting: http://jsfiddle.net/rbxssmx8/.
JS:
var toArray = Function.prototype.call.bind(Array.prototype.slice);
var qAll = document.querySelectorAll.bind(document);
var _$ = (function() {
function dom(selector) {
if(!(this instanceof dom)) {
return new dom(selector);
}
this.elements = toArray(qAll(selector));
}
dom.prototype.iterate = function(func) {
this.elements.forEach(func);
return this;
};
dom.prototype.addClass = function() {
var klasses = arguments;
return this.iterate(function(element) {
element.classList.add.apply(element.classList, klasses);
});
};
dom.extend = function(name, func) {
this.prototype[name] = func;
};
dom.ready = function(func) {
document.addEventListener("DOMContentLoaded", func);
};
return dom;
})();
_$.extend("removeClass", function() {
var klasses = arguments;
return this.iterate(function(element) {
element.classList.remove.apply(element.classList, klasses);
});
});
_$("div").addClass("gray");
var $el = _$("div:last-of-type");
$el.removeClass("gray");
So I read this post on What's wrong with extending the DOM and the alternative suggested by the author was to use Object Wrappers. A quick search on that led me to this post on SO: Using object wrappers to extend the JavaScripts DOM?
Coupled with some insight from #DRD's answer, I updated my code:
(function() {
var microLib = function (selector){
return new Dom(selector);
};
function Dom(selector)
{
var selector_value = selector.slice(1);
this.element = document.getElementById(selector_value);
}
Dom.prototype.func_1 = function(){
return 'first';
};
Dom.prototype.func_2 = function(){
return 'second';
};
microLib.extend = function(name, func){
Dom.prototype[name] = func;
};
window._$ = microLib;
})();
And then whenever you want to extend and add another function, do this afterwards:
_$.extend('func_3', function(){ //this is inline with my earlier question
return 'third';
});
Works like a charm! And definitely the safer option compared to extending Element.prototype.
I wanna get the next functionality:
var newString = String;
newString.prototype.reverse = function () {
return this.split("").reverse().join("")
}
var a = 'hello';
var b = newString('hello');
a.reverse();//reverse is not a function
b.reverse();//olleh
try extend .prototype before add function and doesn't work, i don't even know if it is possible.
You could do the following:
var newString = function(initialVal) {
var val = new String(initialVal);
val.reverse = function () {
return this.split("").reverse().join("")
};
return val;
};
var a = 'hello';
var b = newString('hello');
a.reverse();//reverse is not a function
b.reverse();//olleh
It sounds like you're looking for:
String.prototype.reverse = function () {
return this.split("").reverse().join("")
}
var a = 'hello';
alert(a.reverse());
Note that extending built in objects like "String" is highly controversial at best.
let's say I have code like this:
var object1 = {};
object1.class1 = function() {
this.property1 = null;
this.property2 = 'ab';
}
in this case, what does 'this' stand for? object1 or class1? And whenever I want to define a class constructor inside an object, what is the best way to do it?
For class1, because you can't make an object of type object1.
However, if the code would be:
function object1() {
this.class1 = function() {
this.property1 = null;
this.property2 = 'ab';
}
}
You could have:
var obj = new object1();
obj.class1();
obj.property2; // => 'ab';
var cls = new obj.class1();
cls.property2; // => 'ab';
So it could depend on context.
If you call it like so:
object1.class1();
Then this will refer to object1.