Reputation: 458
Ok, long story short, i have 2 classes(functions) and need extend one from second.. In the end of hard day, i wrote simply solution, but then i come home, i thought this is wrong.. But.. Actually it's working, only i don't understand why.. So for example i have 2 functions:
function aa() {
var r = "aaaa";
this.method = function(){
console.log(r);
}
}
function bb() {
var e = "bbbb";
this.method2 = function(){
console.log(e);
}
}
var a = new aa();
var b = new bb();
After i use this function to merge them:
var merge = function(one, two) {
for(var method in two) {
one[method] = two[method];
}
return one;
}
var c = merge(a, b);
And this is work fine.. so question is why? I guess in 'merge' function, i just add to first object method of second, but this method used private variable what not defined in first object, why he sees it?
Upvotes: 1
Views: 1255
Reputation: 113866
That is basically how closures work. Your code can be simplified to this:
var bar;
(function foo () {
var x = 10;
bar = function () {
alert(x);
}
})();
// Now that we're outside of foo:
bar(); // bar can still see "x".
// Even if you do this:
var x = 0;
bar(); // bar still sees x=10
Upvotes: 0
Reputation: 9399
Notice that you didn't copy the method2
function from one prototype to another - you added a reference to method2
in aa
.
As long as bb
exists, method2
will be able to access bb
's variable e
. Specially since e
was declared in a scope that is visible to method2
.
Upvotes: 1
Reputation: 55688
The r
and e
values are included in the scope of the method
and method2
functions. Even after these functions are moved around, they still maintain a reference to variables in the scope in which they were defined. This is called a closure. More: How do JavaScript closures work?
Upvotes: 4
Reputation: 840
This is jQuery's deep copy method they use for their .extend() api
function() {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
Upvotes: -1