from Bad Parts: Appendix B - JavaScript: The Good Parts
How often do these issues come up?
how many with bugs have you wrangled?
this
1. var obj = {
2. fullName: "John K. Paul",
3. alertName: function(greeting){
4. alert(greeting + " " + this.fullName);
5. }
6. };
7.
8. obj.alertName("Hey"); // Hey John K. Paul
1. var obj = {
2. fullName: "John K. Paul",
3. alertName: function(greeting){
4. alert(greeting + " " + this.fullName);
5. }
6. };
7.
8. var alertName = obj.alertName;
10. alertName("Hey"); // Hey undefined
11. // this is the global object unless in strict mode
1. var obj = {
2. fullName: "John K. Paul",
3. alertName: function(greeting){
4. alert(greeting + " " + this.fullName);
5. }
6. };
7.
8. var alertName = obj.alertName;
10. var newContext = {
11. fullName: "John Doe"
12. };
13. alertName.call(newContext, "Hey"); // Hey John Doe
1. var obj = {
2. fullName: "John K. Paul",
3. alertName: function(greeting){
4. alert(greeting + " " + this.fullName);
5. }
6. };
7.
8. var alertName = obj.alertName;
10. var newContext = {
11. fullName: "John Doe"
12. };
13. alertName.apply(newContext, ["Hey"]); // Hey John Doe
1. var Foo = function(){
2. this.sayHey = function(){
3. alert("Hey");
4. }
5. }
6.
7. //this is a newly created object
8. var newObject = new Foo();
10. newObject.sayHey() // Hey
1. var obj = {
2. fullName: "John K. Paul",
3. alertName: function(greeting){
4. alert(greeting + " " + this.fullName);
5. }
6. };
7.
8. var alertName = obj.alertName;
10. var newContext = {
11. fullName: "John Doe"
12. };
13. boundFunc = alertName.bind(newContext, "Hey");
14. boundFunc(); // Hey John Doe
In ES6
1. // with fat arrow inner function
2. var myObj = {
3. longOuter: function() {
4. console.log(this); // this is myObj
5. var fatInner = () =>
6. console.log(this); // this is also myObj
7. fatInner();
8. }
10.}
11.
12.myObj.longOuter();
from howtonode.org
Is it classes?
Is it blueprints?
Is it super?
No, none of these
This is what we really care about
Write code once, use in multiple situations
prototypal inheritance makes this easy
don't think about new, super, and extends
don't even think about JavaScript's prototype property
Prototypal inheritance is about fallbacks
1. var base = {
2. firstName: "John",
3. lastName: "Paul",
4. getFullName: function(){
5. return this.firstName + " " + this.lastName;
6. },
7. }; // base is the fallback
8.
9. // where the magic happens
10. var obj = Object.create(base);
11. obj.alertName = function(){
12. alert(this.getFullName());
13. };
14.
15. obj.alertName(); // John Paul
16.
17. // this is code reuse!
18. alert("getFullName" in obj) //true
19. alert(obj.getFullName === base.getFullName) //true
Not all js environments have Object.create
But we have a solution for < IE9
1. Object.closeToCreate = function (o) {
2. function F() {}
3. F.prototype = o;
4. return new F();
5. };
prototype is double speakfallbackOfObjectsCreatedWithNew would be better
1. var arr = [1,2,3];
2. var out = [];
3. for(var i = 0; i<arr.length;i++) {
4. var item = arr[i];
5. out.push(function(){ alert(item); });
6. }
7.
8. out.forEach(function(func){ func(); });
1. var arr = [1,2,3];
2. var out = [];
3. for(var i = 0; i<arr.length;i++) {
4. (function(valueToAlert){
5. var item = valueToAlert;
6. out.push(function(){ alert(item); });
7. })(arr[i]);
8. }
9.
10. out.forEach(function(func){ func(); });
do keywordlet
1. var arr = [1,2,3];
2. var out = [];
3. for(var i = 0; i<arr.length;i++) {
4. let item = arr[i]; // block scoped
5. out.push(function(){ alert(item); });
6. }
7.
8. out.forEach(function(func){ func(); });
1. testFunc();
2. var testFunc = function(){ alert("hey!"); };
1. testFunc();
2. (function testFunc(){ alert("hey!"); });
1. testFunc();
2. function testFunc(){ alert("hey!"); };
1. (function(){
2. var hello = "world";
3. //some other code
4. var expression = function(){ alert("expression!"); };
5. var foo = "bar";
6. function declaration(){ alert("declaration!"); };
7. })();
1. (function(){
2. function declaration(){ alert("declaration!"); };
3. var foo, hello, expression;
4. hello = "world";
5. //some other code
6. expression = function(){ alert("expression!"); };
7. foo = "bar";
8. })();
1. function declaration(){} // hoisted
2.
3. (function expression(){
4. function declaration(){} // hoisted
5. }())
6.
7. var expression = function(){}; // not hoisted
8.
10. var expression = function expression(){}; // not hoisted
11.
12. (function expression(){})(); // not hoisted
13.
14. new function expression(){}; // not hoisted
15.
16. 0, function expression(){}; // not hoisted
17.
18. void function expression(){} // not hoisted
19. +function expression(){} // not hoisted
Only easy rule - if there's no name, it's a expression
this can be set in