I found one interesting project on github which deals with pdf rendering in the browser.
I tried to read the code because I'm interested in this topic but I realized that my javascript 开发者_JAVA百科knowledge is poor (insuficient).
There are constructs like:
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
constructor.prototype = {
};
var types = [
"Bool", "Int", "Real", "String", "Name", "Null",
"Array", "Dict", "Stream", "Ref",
"Cmd", "Error", "EOF", "None"
];
for (var i = 0; i < types.length; ++i) {
var typeName = types[i];
constructor[typeName] = i;
constructor.prototype["is" + typeName] =
(function (value) {
return this.type == i &&
(typeof value == "undefined" || value == this.value);
});
}
constructor.prototype.lookup = function(key) {
function lookup(key) {
if (!(this.value.contains(key)))
return Obj.nullObj;
return this.value.get(key);
}
}
Object.freeze(constructor.trueObj = new constructor(constructor.Bool, true));
Object.freeze(constructor.falseObj = new constructor(constructor.Bool, false));
Object.freeze(constructor.nullObj = new constructor(constructor.Null));
Object.freeze(constructor.errorObj = new constructor(constructor.Error));
Object.freeze(constructor.prototype);
Object.freeze(constructor);
return constructor;
})();
You can see more of them in the link above.
Could you please advise me some resources which to study to be able to understand the code in the project with ease and even better to contribute later to the project?
Working outside in, the first big concept here are anonymous funcitons.
var Obj = (function() { /* do work */})();
Simply, put, we are making an anonymous function, and then immediately execturing it, and assigning the return from the anonymous function to an variable named Obj.
Why would anyone want to do it?
In this case, it is used to create a private scope. Local variables in javascript are scoped to the function where they are defined. For example:
function test() {
var a = 10;
}
// a is not defined here.
In the last example, a
really only exists inside the scope of the function that
defined it. Javascript is a little tricky this regard because by omitting the var
keyword, you can define a global variable.
So in the example you've given, they are using this anonymous function to build a scope for some variables that will be used, but will ultimately want to be thrown away as soon as the function is finished executing.
Next:
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
})();
This creates a new function called constructor
. Its important to note that javascript functions
are first-class objects, which means they work a lot like any other object, and can be assigned
to a variable. This function is scoped to the anonymous function. So trying to get constructor
out
side of the scope of its function, doesn't work. For example
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
})();
typeof(constructor) // <= undefined
So far, if you were to execute the snippits so far, then Obj
would have been undefined. Now
let's skip ahead a bit to end, and look at the return.
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
return constructor;
})();
So when the anonymous function gets invoked, it returns the constructor. This function that gets
passed back is assigned to Obj
. This hands back the constructor, out of the local scope of the
function, and assigns to the variable. You would then be able to invoke it
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
// SNIP
return constructor;
})();
var o1 = new Obj("t", "v");
o1.type // <= "t"
o1.value // <= "v"
Next we've got an interesting line
var Obj = (function() {
function constructor(type, value) {
this.type = type;
this.value = value;
}
constructor.prototype = { };
// SNIP
return constructor;
})();
This sets the prototype for the constructor to an empty object. Explaining the details of prototypes is
a bit of the scope of this post, but an over-simplication is that a prototype defines the instance methods
that are available to an object that is created by a constructor. A single 'prototype' is shared between
and will be used to define the methods that will be available to the objects that are constructed by
calling new Obj()
.
Next we have a locally defined array
var types = [
"Bool", "Int", "Real", "String", "Name", "Null",
"Array", "Dict", "Stream", "Ref",
"Cmd", "Error", "EOF", "None"
];
Remember because we are inside of a function, this variable is bound within the outer anonymous function's scope.
Next we loop through that array, and set up some stuff.
for (var i = 0; i < types.length; ++i) {
var typeName = types[i];
constructor[typeName] = i;
constructor.prototype["is" + typeName] =
(function (value) {
return this.type == i &&
(typeof value == "undefined" || value == this.value);
});
}
Two things interesting happen here. First, it sets a 'static' property off of the constructor
, and then
creates a new function on the constructor's prototype. This function is called "is" + typeName
. So we should
generate a bunch of instance methods named stuff like: "isBool", "isInt", "isReal", and so on.
constructor.prototype.lookup = function(key) {
function lookup(key) {
if (!(this.value.contains(key)))
return Obj.nullObj;
return this.value.get(key);
}
}
Next we define another instance method called lookup
and does some work.
Lastly we create some static properties off of our constructor, and freeze them (so they can't be changed or extended)
Once its all said and done, Obj
, should point to a constructor function, and we should be able to say things like:
var myType = new Obj("MyType",undefined);
myType.isBool(undefined) //instance method
Obj.Bool // static property
Anyway, I hope that helped a little bit explaining a few of the concepts that were being used. The big take-away should
be that a function
can be used to control scope, and that functions are First-class functions, and can be handed around
like variables. You can also reference a property off a object using dot notation (obj.property
) or bracket notation
(obj["property"]
).
There are a bunch of more things to learn, and all of the book suggestions are solid in this thread. If it hasn't been mentioned I would also recommend Eloquent JavaSript by Haverbeke.
Douglas Crockford's book JavaScript: The Good Parts is a great place to gain an appreciation of the power in JavaScript, while steering you away from the ugly (or downright dangerous) parts. His website also has a collection of interesting articles about the language. I recommend both.
Maybe some of these links will help you out:
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model, https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript, https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Objects, https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_Revisited,
I can refer some links
Can I name a javascript function and execute it immediately?
http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
I hope you can learn with them
I find the blogs by Douglas Crockford(http://www.crockford.com/), John Resig(http://ejohn.org/blog/) useful for intermediate to advanced concepts. Looking at other people's code(just like what you are doing) can also be helpful. At the end of the day though nothing beats actually trying out the concept and for that the trusty Firebug console is still the best.
精彩评论