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