0
var foo = {}

class bar {
  fiddle() {
    alert('boo');
  }
} 

Object.assign(foo, new bar());

foo.fiddle(); 

Why doesn't this work? I see foo.fiddle is not a function.

In my real-world situation, I know that fiddle exists and I just want to copy it into an existing instance of a different class. Something like

otherInstance['fiddle'] = bar['fiddle']

...but I'm aware that this syntax won't work.

I also find it strange that this guy's example demonstrates Object.assign copying a function via:

let x = {a: y => y * 2}
let z = Object.assign({}, x)
console.log(z.a(5)); // 10

Clarified:

let calculator = {double: y => y * 2}
let clone = Object.assign({}, calculator)
alert(clone.double(5)); // 10

Modified:

let calculator = {double: y => y * 2}
let clone = {}
Object.assign(clone, calculator)
alert(clone.double(5)); // 10

But my initial example using a class instance doesn't work, presumably due to the way that prototype is mysteriously related.

UPDATE

For now, I've decided to convert a bunch of classes into objects so this isn't as much of a nightmare:

class foo {
  foodle() {
    console.log('1')
  }
}

const bar = {
  fiddle: () => {
    console.log('2');
  }
}

var test = new foo();
var test2 = Object.create(bar);

Object.assign(test, bar);

test.foodle(); // 1
test.fiddle(); // 2

My inner purist would enjoy using classes for all of my components so if there's a solution that allows me to revert the downgrade to objects, I'm all ears!

UPDATE 2

I'm a dummy, this approach actually does work:

var foo = {}

class bar {
  fiddle() {
    alert('boo');
  }
} 

var barInstance = new bar();

foo['fiddle'] = barInstance['fiddle'];

foo.fiddle(); // boo
BLAZORLOVER
  • 1,971
  • 2
  • 17
  • 27
  • See https://stackoverflow.com/a/44782052/294949, though if it were mine, I might want clone's constructor to run, so I'd consider a static cloning method, that takes a bar instance as a param, creates another, and matches it's state to the param. – danh Oct 28 '22 at 22:10
  • thanks @danh - do you have a recommendation if I don't want to create a new object, and if I don't care about the constructor? Given an existing `targetObject` that may or may not be an instance of an arbitrary class, how do I reassign a known method from an instance of some other class to this object such that I can invoke `targetObject.methodName()`? – BLAZORLOVER Oct 28 '22 at 22:20
  • If the fiddle method refers to this.someProp, you'll want that prop, also, right? – danh Oct 28 '22 at 22:27
  • @danh I'm working on known instance methods only at the moment - I've cloned props enough that I'm comfortable handling that separately as needed. – BLAZORLOVER Oct 28 '22 at 22:30
  • Why would `otherInstance['fiddle'] = bar['fiddle']` not work? – Ry- Oct 28 '22 at 22:53
  • thanks @Ry- I'm an idiot, updated. Feel free to drop an answer if you want points otherwise I'll self-answer. – BLAZORLOVER Oct 28 '22 at 23:07

1 Answers1

1

JavaScript prototyping is not that mysterious - class methods are held in the class function's prototype property, from where they are inherited by class instance object. Hence one way to assign the method of one class to an instance of another would be to use the pattern

otherInstance['fiddle'] = Bar.prototype.fiddle

where Bar is the name of the class with the fiddle method.

You can also find class methods from an instance of the class by looking where it inherits its methods from:

otherInstance.fiddle = Object.getPrototypeOf( bar).fiddle

or simply let it be inherited as usual:

otherInstance.fiddle = bar.fiddle

where bar is an instance of Bar (not the class itself), which necessarily implies that the first object in its prototype chain is Bar.prototype.

Object.defineProperty could be used instead of assignment to add the method without making it enumerable. Consider using the class extends syntax if you want a child class to inherit all the properties of a parent class.

Regarding Object.assign: it only assigns enumerable own properties of one object to another. Class methods, however, are neither enumerable nor own properties of class instances.

traktor
  • 17,588
  • 4
  • 32
  • 53