Functions results in angularjs view - javascript

I'm afraid this question is pretty stupid....
Using the {{current.name}} syntax I can show the name of $scope.current in the view. I set current when I switch from the list view (/mythings) to editing an item (/mythings?id=someId).
Actually this is redundant as I have the information both in the $location and in $scope.current. This redundancy makes it more complicated to understand, so I'd like to get rid of it.
I replaced current by a current item returning function and hoped it would work (like it does in many other cases). But it doesn't, I need to write {{current().name}} everywhere, which I tend to forget.
Maybe I'm doing it all wrong? I'm a beginner here.
Is there a way to make it work? Somehow bless current so it always gets evaluated before use?

Both alternatives discussed have pros and cons:
Using a property (current) is easier (and more natural) to reference in the view, but it needs to be manually kept in sync with the location.
Using a function (current()) takes care of the keeping in sync issue, but is less intuitive.
All things considered, I would value the auto-syncing feature higher and go for the second alternative (current() function).
But, what if we could get a third option that combines the best of both worlds ?
And in fact we can :)
We can use the concept of Object Properties, introduced by ECMAScript 5, and define some "computed properties" for our $scope (or service?).
Without getting into much detail (see the docs for more details), we could augment a scope like this:
.cotroller('someCtrl', function ($location, $scope) {
Object.defineProperty($scope, 'current', {
get: function () {
return {
name: $location.path();
id: $location.search('id');
};
}
});
Now, we can access $scope.current.name and $scope.current.id as if current were a normal property of $scope (intuitiveness !) and current will be automatically computed based on the current location (auto-sync !).
Thank you ECMAScript 5 :)
This article provides a simple and clear introduction to the concept.

Related

Initializing variable as equal to another without having future changes to the former affect the latter in AngularJS

I know people mostly refer to two-way binding when it comes to variables displayed in the HTML, but I keep running into this same problem and realized there is something fundamental about Angular that I'm not understanding.
To set up this question, I am currently developing an RPG browser game. I want each character to have baseStats which are represented as:
'baseStats' : {
'defense' : 5,
'strength' : 3,
'speed' : 7
}
but during the course of the battle, they may be 'buffed' or 'debuffed', so I want to be able to track those changes without permanently changing the characters stats, so baseStats exists to preserve the 'original' state of the stats.
vm.restoreAll = function() {
angular.forEach(vm.activeAllies, function(ally) {
ally.stats.defense = ally.baseStats.defense;
ally.stats.strength = ally.baseStats.strength;
ally.stats.strength = ally.baseStats.speed;
});
};
This works exactly as I intend it to. Each of these stats is reset to the baseStat
vm.restoreAll = function() {
angular.forEach(vm.activeAllies, function(ally) {
ally.stats = ally.baseStats;
});
}
This is obviously more readable and terse, but unfortunately if I make changes to ally.stats from elsewhere in the application, those changes affect the baseStats as well. I'm confused why this would be as they seem to be effectively the same exact thing.
Your issue is not really specific to Angular but Javascript in general. When you pass object values around to different variables you are not passing the actual object value but just a reference to the object. So the object value itself only exists in one place in memory and each variable holds a reference to that location.
This blog post explains further: http://nsono.net/javascript-pass-by-value-or-pass-by-reference/
As the other comments already explain using Angular's copy function will cause an entire new object to be created and stored in memory and fix your issue.
There are various non-Angular ways of cloning objects as well, some described here: http://heyjavascript.com/4-creative-ways-to-clone-objects/
Probably the most concise: JSON.parse(JSON.stringify(myObject))

Angular.js - Performance implications of binding a model to be watched, using $watchCollection

I'm trying to get a better understanding of a new codebase, and haven't found a ton of info (or maybe I'm not fully understanding what I have read) about the performance implications of some choices that were made. The previous maintainer isn't available for insight.
Each controller is set up to make its data request before being rendered initially using this pattern:
$routeProvider.when('/path', {
resolve: { someMethod: function($q) {
var deferred = $q.defer();
.... do some stuff ...
return deferred.promise;
}
});
This is then injected into the controller - that part makes sense and from my understanding is more performant because you're saving digests by waiting for the data to come through first. A loading state is shown by default and removed when we digest.
The value of the injected param - in this case someMethod - is then assigned to this.someModel.
Throughout the controller, remaining methods and properties are set with this.doStuff = function() { ... }, this.property = 'some string', etc.
In the end, a watch is setup and properties made available to the $scope by setting a $watchCollection like this:
$scope.$watchCollection(angular.bind(this.someModel, function() {
return this;
}), function(newTitle, oldTitle) {
if (newTitle.title !== oldTitle.title)
{
self.updateThings(newTitle);
}
});
I understand that it's binding the context of the watch to the current context of this, then watching to changes on its properties using $watchCollection which will perform shallow reference checks of its top level properties.
Per this article I get that simply using properties in my templates with {{ property }} will cause them to be watched, but in this case they aren't watched until they're bound to the $watchCollection.
Of course this is less expensive than using $watch and passing it true for the optional object equality param, but is it better or worse from a performance perspective than putting things directly onto $scope? Why, specifically?
I've never seen it done this way before, so any readings, insights, or things that could give me a better understanding will be greatly appreciated.
The only real thing I can think of is that the author wanted to keep everything off the scope directly, only populating properties of the controller instance, which will be available on the scope via the property specified in the controllerAs property on the route definition object.
However, when doing it that way, if you want to set up $watches on the scope to be notified of changes to something, you can't, because you don't actually know what property of the scope it will be published on.
You could settle on a convention, such as vm, ctrl or whatever, for the controllerAs value, but that is not ideal and is fragile and not really a concern of the controller code itself. But if you made that concession, you could use $scope.$watchCollection('vm.someModel', ... instead.
One final possible reason is that $scope.$watch() and $scope.$watchCollection() always ultimately end up dealing with a function as the thing they use to get the value of the thing being watched during the digest. If you pass a string, it uses the $parse service under the covers to turn it into a function. If you pass a function directly, no conversion is necessary, so this can be perceived as a minor performance improvement.
The real reason(s) may be one, all or none of these, but they are valid reasons for adopting this approach. I actually admire it for its purity and strict adherence to "controller as", which is the in-vogue strategy encouraged by the Angular team and community at the moment.

Creating a global variable from a function's return value

I'm looking at Addy Osmani's gist for a publication/subscription pattern here:
https://github.com/addyosmani/pubsubz/blob/master/pubsubz.js
He surfaces his object as a global like this:
;(function ( window, doc, undef ) {
var topics = {},
subUid = -1,
pubsubz ={};
....
getPubSubz = function(){
return pubsubz;
};
window.pubsubz = getPubSubz();
What is the value of creating that getPubSubz function? Wouldn't it be more straightforward to simply write:
window.pubsubz = pubsubz;
Yes, in this case, because getPubSubz is only called in one place, immediately after declaring it, it could safely be inlined.
It's hard to say exactly what the author had in mind, but in a growing code base there may be some value to having a "getter" function which could be modified if the act of getting the pubsubz object required more advanced logic.
It absolutely would be.
There are only two potential reasons why a getter would be used in this case:
There was previously some additional code inside the getter (logging, perhaps)
Addy Osmani's just following good practice*, and including a getter—even adding the opportunity to add additonal code in the future.
Through the power of GitHub, we can actually eliminate option one, as the getter was added in its current state—so I think we can conclusively say that it's just a matter of good practice here.
*as jantimon alludes to in the comments below, this isn't particularly advantageous in most cases (including this one) and this code does not necessarily need to followed as an example.

Why would I need to freeze an object in JavaScript?

It is not clear to me when anyone would need to use Object.freeze in JavaScript. MDN and MSDN don't give real life examples when it is useful.
I get it that an attempt to change such an object at runtime means a crash. The question is rather, when would I appreciate this crash?
To me the immutability is a design time constraint which is supposed to be guaranteed by the type checker.
So is there any point in having a runtime crash in a dynamically typed language, besides detecting a violation better later than never?
The Object.freeze function does the following:
Makes the object non-extensible, so that new properties cannot be added to it.
Sets the configurable attribute to false for all properties of the object. When - configurable is false, the property attributes cannot be changed and the property cannot be deleted.
Sets the writable attribute to false for all data properties of the object. When writable is false, the data property value cannot be changed.
That's the what part, but why would anyone do this?
Well, in the object-oriented paradigm, the notion exists that an existing API contains certain elements that are not intended to be extended, modified, or re-used outside of their current context. The final keyword in various languages is the most suitable analogy of this. Even in languages that are not compiled and therefore easily modified, it still exists, i.e. PHP, and in this case, JavaScript.
You can use this when you have an object representing a logically immutable data structure, especially if:
Changing the properties of the object or altering its "duck type" could lead to bad behavior elsewhere in your application
The object is similar to a mutable type or otherwise looks mutable, and you want programmers to be warned on attempting to change it rather than obtain undefined behavior.
As an API author, this may be exactly the behavior you want. For example, you may have an internally cached structure that represents a canonical server response that you provide to the user of your API by reference but still use internally for a variety of purposes. Your users can reference this structure, but altering it may result in your API having undefined behavior. In this case, you want an exception to be thrown if your users attempt to modify it.
In my nodejs server environment, I use freeze for the same reason I use 'use strict'. If I have an object that I do not want being extended or modified, I will freeze it. If something attempts to extend or modify my frozen object, I WANT my app to throw an error.
To me this relates to consistent, quality, more secure code.
Also,
Chrome is showing significant performance increases working with frozen objects.
Edit:
In my most recent project, I'm sending/receiving encrypted data between a government entity. There are a lot of configuration values. I'm using frozen object(s) for these values. Modification of these values could have serious, adverse side effects. Additionally, as I linked previously, Chrome is showing performance advantages with frozen objects, I assume nodejs does as well.
For simplicity, an example would be:
var US_COIN_VALUE = {
QUARTER: 25,
DIME: 10,
NICKEL: 5,
PENNY: 1
};
return Object.freeze( US_COIN_VALUE );
There is no reason to modify the values in this example. And enjoy the benefits of speed optimizations.
Object.freeze() mainly using in Functional Programming (Immutability)
Immutability is a central concept of functional programming because without it, the data flow in your program is lossy. State history is abandoned, and strange bugs can creep into your software.
In JavaScript, it’s important not to confuse const, with immutability. const creates a variable name binding which can’t be reassigned after creation. const does not create immutable objects. You can’t change the object that the binding refers to, but you can still change the properties of the object, which means that bindings created with const are mutable, not immutable.
Immutable objects can’t be changed at all. You can make a value truly immutable by deep freezing the object. JavaScript has a method that freezes an object one-level deep.
const a = Object.freeze({
foo: 'Hello',
bar: 'world',
baz: '!'
});
When you're writing a library/framework in JS and you don't want some developer to break your dynamic language creation by re-assigning "internal" or public properties.
This is the most obvious use case for immutability.
With the V8 release v7.6 the performance of frozen/sealed arrays is greatly improved. Therefore, one reason you would like to freeze an object is when your code is performance-critical.
What is a practical situation when you might want to freeze an object?
One example, on application startup you create an object containing app settings. You may pass that configuration object around to various modules of the application. But once that settings object is created you want to know that it won't be changed.
This is an old question, but I think I have a good case where freeze might help. I had this problem today.
The problem
class Node {
constructor() {
this._children = [];
this._parent = undefined;
}
get children() { return this._children; }
get parent() { return this._parent; }
set parent(newParent) {
// 1. if _parent is not undefined, remove this node from _parent's children
// 2. set _parent to newParent
// 3. if newParent is not undefined, add this node to newParent's children
}
addChild(node) { node.parent = this; }
removeChild(node) { node.parent === this && (node.parent = undefined); }
...
}
As you can see, when you change the parent, it automatically handles the connection between these nodes, keeping children and parent in sync. However, there is one problem here:
let newNode = new Node();
myNode.children.push(newNode);
Now, myNode has newNode in its children, but newNode does not have myNode as its parent. So you've just broken it.
(OFF-TOPIC) Why are you exposing the children anyway?
Yes, I could just create lots of methods: countChildren(), getChild(index), getChildrenIterator() (which returns a generator), findChildIndex(node), and so on... but is it really a better approach than just returning an array, which provides an interface all javascript programmers already know?
You can access its length to see how many children it has;
You can access the children by their index (i.e. children[i]);
You can iterate over it using for .. of;
And you can use some other nice methods provided by an Array.
Note: returning a copy of the array is out of question! It costs linear time, and any updates to the original array do not propagate to the copy!
The solution
get children() { return Object.freeze(Object.create(this._children)); }
// OR, if you deeply care about performance:
get children() {
return this._PUBLIC_children === undefined
? (this._PUBLIC_children = Object.freeze(Object.create(this._children)))
: this._PUBLIC_children;
}
Done!
Object.create: we create an object that inherits from this._children (i.e. has this._children as its __proto__). This alone solves almost the entire problem:
It's simple and fast (constant time)
You can use anything provided by the Array interface
If you modify the returned object, it does not change the original!
Object.freeze: however, the fact that you can modify the returned object BUT the changes do not affect the original array is extremely confusing for the user of the class! So, we just freeze it. If he tries to modify it, an exception is thrown (assuming strict mode) and he knows he can't (and why). It's sad no exception is thrown for myFrozenObject[x] = y if you are not in strict mode, but myFrozenObject is not modified anyway, so it's still not-so-weird.
Of course the programmer could bypass it by accessing __proto__, e.g:
someNode.children.__proto__.push(new Node());
But I like to think that in this case they actually know what they are doing and have a good reason to do so.
IMPORTANT: notice that this doesn't work so well for objects: using hasOwnProperty in the for .. in will always return false.
UPDATE: using Proxy to solve the same problem for objects
Just for completion: if you have an object instead of an Array you can still solve this problem by using Proxy. Actually, this is a generic solution that should work with any kind of element, but I recommend against (if you can avoid it) due to performance issues:
get myObject() { return Object.freeze(new Proxy(this._myObject, {})); }
This still returns an object that can't be changed, but keeps all the read-only functionality of it. If you really need, you can drop the Object.freeze and implement the required traps (set, deleteProperty, ...) in the Proxy, but that takes extra effort, and that's why the Object.freeze comes in handy with proxies.
I can think of several places that Object.freeze would come in very handy.
The first real world implementation that could use freeze is when developing an application that requires 'state' on the server to match what's in the browser. For instance, imagine you need to add in a level of permissions to your function calls. If you are working in an application there may be places where a Developer could easily change or overwrite the permission settings without even realizing it (especially if the object were being passed through by reference!). But permissions by and large can never change and error'ing when they are changed is preferred. So in this case, the permissions object could be frozen, thereby limiting developer from mistakenly 'setting' permissions erroneously. The same could be said for user-like data like a login name or email address. These things can be mistakenly or maliciously broken with bad code.
Another typical solution would be in a game loop code. There are many settings of game state that you would want to freeze to retain that the state of the game is kept in sync with the server.
Think of Object.freeze as a way to make an object as a Constant. Anytime you would want to have variable constant, you could have an object constant with freeze for similar reasons.
There are also times where you want to pass immutable objects through functions and data passing, and only allow updating the original object with setters. This can be done by cloning and freezing the object for 'getters' and only updating the original with 'setters'.
Are any of these not valid things? It can also be said that frozen objects could be more performant due to the lack of dynamic variables, but I haven't seen any proof of that yet.
The only practical use for Object.freeze is during development. For production code, there is absolutely no benefit for freezing/sealing objects.
Silly Typos
It could help you catch this very common problem during development:
if (myObject.someProp = 5) {
doSomething();
}
In strict mode, this would throw an error if myObject was frozen.
Enforce Coding Protocol / Restriction
It would also help in enforcing a certain protocol in a team, especially with new members who may not have the same coding style as everyone else.
A lot of Java guys like to add a lot of methods to objects to make JS feel more familiar. Freezing objects would prevent them from doing that.
I could see this being useful when you're working with an interactive tool. Rather than:
if ( ! obj.isFrozen() ) {
obj.x = mouse[0];
obj.y = mouse[1];
}
You could simply do:
obj.x = mouse[0];
obj.y = mouse[1];
Properties will only update if the object isn't frozen.
Don't know if this helps, but I use it to create simple enumerations. It allows me to hopefully not get duff data in a database, by knowing the source of the data has been attempted to be unchangeable without purposefully trying to break the code. From a statically typed perspective, it allows for reasoning over code construction.
All the other answers pretty much answer the question.
I just wanted to summarise everything here along with an example.
Use Object.freeze when you need utmost surety regarding its state in the future. You need to make sure that other developers or users of your code do not change internal/public properties. Alexander Mills's answer
Object.freeze has better performance since 19th June, 2019, ever since V8 v7.6 released. Philippe's answer. Also take a look at the V8 docs.
Here is what Object.freeze does, and it should clear out doubts for people who only have surface level understanding of Object.freeze.
const obj = {
name: "Fanoflix"
};
const mutateObject = (testObj) => {
testObj.name = 'Arthas' // NOT Allowed if parameter is frozen
}
obj.name = "Lich King" // Allowed
obj.age = 29; // Allowed
mutateObject(obj) // Allowed
Object.freeze(obj) // ========== Freezing obj ==========
mutateObject(obj) // passed by reference NOT Allowed
obj.name = "Illidan" // mutation NOT Allowed
obj.age = 25; // addition NOT Allowed
delete obj.name // deletion NOT Allowed

Best practice: Javascript/Jquery saving variable for later use

I'm sure, this question has been answered somewhere before but I just couldn't find it.
If within a function a variable has been defined, what is the best practice to save it for later use? 1. Saving it "globally"?
foo = 'bar';...function bar(){
...
foo = 'bat';
return foo;
}...
Here, the variable will be altered later on.
2. Or saving it within a hidden form field within the HTML-DOM?
`Thanxs!
Saving it as a global JavaScript variable is by far the most efficient.
EDIT: If the data you want to save is associated with an element on the page (for example, each row in a table has a bit of data associated with it), and you are using jQuery, there is a data() method which is more efficient than setting an attribute on the element or something similar.
It depends on the context, but probably: In a variable defined at the top level of a closure that wraps the set of functions to which it applies.
i.e.
var exports = function () {
var stored_data;
function set_data(foo) {
stored_data = foo;
}
function get_data() {
return stored_data;
}
return { get: get_data, set: set_data };
}();
This avoids the risk of other scripts (or other parts of your own, potentially very large, script) overwriting it by accident.
The HTML5 spec has defined a solution to this question: If you are using HTML5, you can specify data attributes in your DOM.
See this page for more info: http://ejohn.org/blog/html-5-data-attributes/
This is now the standardised way of doing it, so I guess that it's considered best practice. Also John Resig, who wrote the blog I linked to above, is the author of JQuery, so if it's good enough for him, who am I to argue.
The really good news is that you don't even have to be using an HTML5-compatible browser for this technique to work - it already works in older browsers; it's just that now it's been encoded into the standard, and there's a defined way to do it.
That said, there's nothing wrong with a global variable in your Javascript as long as you avoid polluting the namespace too much, and it would be more efficient from a performance perspective, so there's plenty of merit in that approach as well.

Categories