I am aware of there is a function ko.utils.unwrapObserable() but it doesn't seem to unwrap an observable that is mapped by the ko.mapping.fromJS() at all:
console.log(listing);
listing = ko.utils.unwrapObservable(listing);
console.log(listing);
And I get the following output:
Object { __ko_mapping__={...}, title=c(), remote_id=c(), more...}
Object { __ko_mapping__={...}, title=c(), remote_id=c(), more...}
Reason I am asking for this is related to another question, basically listing is an instance of a class, which has methods reference its variables, the problem is after listing is mapped to an observable and the class methods will fail because the variables become methods.
My question is, is there a function for me to undo the mapping?
What you need is the ko.mapping.toJS function (see in documentation).
It does is the exact opposite of the ko.mapping.fromJS so it turns an object with observable properties to a plain JavaScript object without any observables:
console.log(listing);
listing = ko.mapping.toJS(listing);
console.log(listing);
Object { title="..,", remote_id="...", more...}
The actual implementation of the ko.mapping.toJS is that it recursively walks through your object properties and calls ko.utils.unwrapObservable on each of them.
Related
const a = Object.create(null);
const b = {};
I want to know the difference between these two objects. When I tried these two in console I have found the second one is showing prototypes. But the first one showing nothing like that. Please try it in your console if didn't get me.
The Object.create() method creates a new object, using an existing
object as the prototype of the newly created object.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
All objects (with the exception of objects created with
Object.create(null)) will have a constructor property. Objects created
without the explicit use of a constructor function (such as object-
and array-literals) will have a constructor property that points to
the Fundamental Object constructor type for that object.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
I'm going through the MDN docs on arrays and when we want to test whether or not an object is an array we use isArray(). However, it's usage is very different to most of the other methods. When you use the regular syntax an error pops up:
console.log([1,2,3].isArray()); // TypeError: [1, 2, 3].isArray is not a function
Whereas this does work:
console.log(Array.isArray([1,2,3]))
I don't understand why isArray() (and a couple of other methods) rely upon some global object rather than just being accessible via the object in question. Why do some methods require the global array object?
rather than just being accessible via the object in question.
Because the whole purpose of Array.isArray is to be called on unknown objects. You don't know whether it's an array, you wouldn't know whether the method was accessible on it. The static method even works with values like null, which would inevitably throw an exception when you tried to invoke a method on them.
Digression:
isArray being callable as an instance method can work. In languages where everything is an object, like Smalltalk, Ruby or Io, even things like nil can have a isNil method. This approach has other problems of course, as with dynamic method dispatch every arbitrary object could overwrite the method and claim to be an array - on the other hand, that's exactly what we want for duck typing.
We could even simulate this in JS using Object.prototype.isArray = () => false; and Array.prototype.isArray = () => true;. Apart from failing on null and undefined, it still wouldn't work with objects that don't inherit from (our realm's) Object.prototype. And JavaScript "properties" that mix data fields and methods don't help either (consider the object parsed from the JSON string {"isArray":"maybe"}). We would always have to expect an exception from either .isArray not being a function, or from it being overwritten with a method that throws.
If we want to go for duck typing in JS, checking whether an object has an integer .length property is usually the way to go. Or more advanced, trying to follow the symbol-based iteration protocol. (That's what Array.from uses, for example).
But since arrays are a bit special in JS (with their magic .length property), we want a built-in reliable way to detect them, and that's what Array.isArray does.
Regarding other static Array methods: Array.of is pretty obvious, it's a factory function (like a constructor) and it can't be an instance method because there is no instance to work with in the first place. For Array.from the situation is a bit more like with isArray, a duck-typing Object.prototype.toArray approach could have worked as well but was dismissed for practical and design reasons.
See also Why were ES5 Object methods not added to Object.prototype?, Why use Object.prototype.hasOwnProperty.call(myObj, prop) instead of myObj.hasOwnProperty(prop)? and Why is it Object.defineProperty() rather than this.defineProperty() (for objects)? for similar discussions.
.isArray() is a static method, it exists on the Array "class" but not on each particular instance. Static methods are called like this: Array.isArray(). Object.create() is another example.
Methods like .map or .slice are not static, so they exist on each instance of the Array "class".
Array (denoted with a captial "A") indicates the JavaScript native Array object. [...] represents an instance of an array. As with many languages, some properties/methods are static. That is, they don't exist on instances only the type. This is often done when the value of the property or behavior of the method doesn't vary from instance to instance, so there's no need for it to be "instance-specific". Figuring out if something is an array, doesn't change from instance to instance (and frankly, doesn't make a lot of sense to ask an array instance if it is an instance of an Array).
I'm having some confusion about instance and class variables. I made a fiddle to display something that seems inconsistent to me.
https://jsfiddle.net/njcfm4n8/1/
I'm familiar with the problem of declaring an array as a subclass property, it should be done in the initialize function, otherwise the array is shared among all instances. The fiddle demonstrates that. However, why is the number property not shared as well?
As per muistooshort and maris' comments, the array happens to work like a class property because it is a reference type. That array really is shared among the instances of your model, but this is more a quirk of javascript and not the intended way to create class variables with Backbone.
An integer on the other hand is a primitive type, along with booleans and strings, and javascript does not pass references to these types but copies them instead.
Arrays, objects, and functions are reference types, while integers, booleans, null and undefined are value types. You can learn more about it here: http://docstore.mik.ua/orelly/webprog/jscript/ch04_04.htm
If you want to make use of class properties, then this section of the Backbone docs is relevant: http://backbonejs.org/#Model-extend
extendBackbone.Model.extend(properties, [classProperties])
To create a Model class of your own, you extend Backbone.Model and provide instance properties, as well as optional classProperties to be attached directly to the constructor function.
I've forked your jsfiddle here https://jsfiddle.net/zn6bu4uf/3/ with this code:
var myModel = Backbone.Model.extend({}, {foo: 0})
console.log(myModel.foo); // 0
myModel.foo++;
console.log(myModel.foo); // 1
var test1 = new myModel();
var test2 = new myModel();
test1.constructor.foo++;
test1.constructor.foo++;
test2.constructor.foo++;
console.log(test1.constructor.foo) // 4
console.log(test2.constructor.foo) // 4
Backbone add your properties (n and arr) to myModel prototype.
Because of that all myModel objects has n and arr in their __proto__ and can access to them.
Array shared among objects because there is no assignment to place where array stored. Push mutates array itself.
But increment actually creating new value and then assigning it to object.
From spec:
test1.n++ will actually do this
get property n from object test1 (if its not there search in test1.__proto__ ... ) and save it virtual variable old_val.
set virtual variable new_val to old_val + 1
set value of property n in object "test1" to value of new_val
return old_val
By spec step 3 not checking initial location of property n. It will add new property to test1.
spec
post increment evaluation
get and put value to object
I want to use filterFilter functionality but I want to reuse the arrays of data instead of creating a new array everytime it runs. So returning an array of indexes and then I can, inside my service, return the items associated to the indexes. This way I can create a $watch export on my service, so I can watch on the real items instead of the filters.
I considered copying the angular filterFilter source, but that isn't maintainable in the long run, what could I do?
Context:
I'm writing a form wizard service that applies a schema to the steps (there are many with slightly different object structures each step), that holds an array of objects. filterFilter returns a new array of objects, so when I modify the object inside the service using a "setter", it's not updating the object itself, but a new (?) created object, and that's no use for me
Javascript has Object.keys( arrayName ) to do just that, but you'll have to include a poly-fill for IE8 or lower.
var a = ['foo', 'bar'];
Object.keys( a ); //returns ['0','1'];
The MDN Object.keys article has an article for implementation if you want to use this with older browsers.
However, upon looking at your problem I think you misread the filter filter. When you use this filter it may return a different array than the input, however every object in that filter is still a reference to an object in the original. So editing any object should modify the original without a problem.
Hope this helps.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?
I noticed that all the methods of a particular object can be called from the actual object instance, i.e., object.method(); or by passing the object to Object.method() as an argument. For example:
var a = ['one', 2, 3, 'four'];
a.reverse();
// OR
Array.reverse(a);
I seemed to get the same behaviour. I was wondering what the difference was and when one would be used over the other?
Object.method(o) looks on the Object object (Object is a real object in JavaScript) for a property called method and tries to call it passing in the variable o. During the call, this will be Object.
o.method() looks on the object referenced by the variable o for a property called method and tries to call it, not passing anything in. During the call, this will be o.
As you can see, they do quite different things.
I noticed that all the methods of a particular object can be called from the actual object instance...or by passing the object to Object.method() as an argument.
No, they cannot. Your example Array.reverse(a) fails on a standard implementation of Array because Array doesn't have a property called reverse and so it can't be called as a function. Edit: You note in the comments that it works in Firefox's scratchpad, and I just verified that. That means Firefox's SpiderMonkey JavaScript engine is applying a non-standard extension to Array which provides a static implementation of reverse. That's specific to Firefox's Array, not general to all objects. (If you make your own Foo, for instance, its prototype functions don't magically get added to Foo as well.)
The standard way to make the near-equivalent to a.reverse() would be via the prototype, like this:
Array.prototype.reverse.call(a);
That does work in standard engines. So let's look at what it does:
It gets the prototype property from Array.
It gets the reverse property from the object it got in #1.
It calls the function that property referenced using the Function#call feature of JavaScript function objects to make this be the argument you pass into call during the course of the function call.
When you create an array, the object gets an underlying prototype. That prototype is the object referenced by Array.prototype when the new array is created. So a has a reverse property because its underlying prototype has a reverse property.
Doing a.reverse() does this:
Gets the reverse property from the a object. Since (normally) a won't have its own property called reverse, standard JavaScript property lookup looks to a's underlying prototype. It finds the property there and uses its value.
Calls that function such that this is a within the call.
As you can see, the end result is the same provided that the underlying prototype of a and Array.prototype still refer to the same object. (It's possible for them not to, although in the case of Array or any other built-in, if someone replaced [as opposed to augmenting] Array.prototype, that would be a Bad Thing(tm).)