Announce

PukiWiki contents have been moved into SONOTS Plugin (20070703)

javascript

JavaScriptのメモ

Table of Contents

Bookmarklet

Examples of bookmarklets modifying URLs.

javascript:(function(){location=location.href.replace('http://ieeexplore.ieee.org','http://ieeexplore.ieee.org.proxy-um.researchport.umd.edu');})()
javascript:(function(){var c='edit';var f=location.href.split('?');if(!f[1].match('=')){location=f[0]+'?cmd='+c+'&page='+f[1];}else{location=f[0]+'?cmd='+c+'&'+f[1].match('page=[^&]+');}})()

Greasemonkey

A template of greasemonkey script modifying a links.

// ==UserScript==
// @name          UMDResearchPort
// @namespace     http://note.sonots.com
// @description   Access Papers via UMD Research Port
// @include       http://scholar.google.com/*
// @include       http://www.cfar.umd.edu/~aswch/enee731.2006/*
// @include       http://www.google.*/*
// ==/UserScript==

var links;
links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
    links[i].href = links[i].href.replace('http://ieeexplore.ieee.org', 'http://ieeexplore.ieee.org.proxy-um.researchport.umd.edu');
    links[i].href = links[i].href.replace('http://www.jstor.org', 'http://www.jstor.org.proxy-um.researchport.umd.edu');
}

Introduction to Object for other language experts

(Almost) Everything is Associative array

The structure concept is definable by using an associative array not only in javascript but also in other languages. For example, think PHP's way $person->name (class object) and $person['name'] (associative array). Just how to write is different. Therefore(?), javascript does not have Struct definition, but uses associative array.

Futhermore, if we set a lambda function to a key of an associative array, it works as a member function of a class. For example, think PHP's way $person->eat() and $person['eat']() (used create_function). Just how to write is different. Therefore(?), javascript does not have Class definition, but uses associative array.

var person = {"name":"hoge"};
alert(person["name"]);
alert(person.name); 

javascript has a syntax sugar to use associative array like object

javascript has a syntax sugar to define a key like a member variable name

var person = {name:"hoge"}; 
alert(person.name);
alert(person["name"]);

Define a member function. Lambda function is set to a key.

var person = {
    name : "hoge",
    eat : function(){alert("Delicious!");},
};
person.eat();
person["eat"]();

Associative Array is not enough for Class

But, simply using associative array to express object is not so good. If we want to define other objects of the same class, we have to copy the object entirely and initialize values. We want only prototype, and want to "new" it. Javascript has such supports that other languages do not (Therefore(?), we do not use associative array to define class in other languages.)

var Person = function(){}; // or function Person(); // it's same
Person.prototype = {
    name : "",
    eat : function(){alert("Delicious!");},
    whoami : function(){alert(this.name);},
};
// Person.prototype.eat = function(){alert("Delicious!");}; is also okay for now
var person = new Person();
person.name = "hoge";
alert(person.name); // "hoge"
person.eat();
// we can easily create an instance of the same class
var person2 = new Person(); 
alert(person.name); // ""
person2.eat();

Javascript chose to use function objects to define class probably because we can define a constructor concurrently (If I were the designer of javascript language, I might've defined another syntax like "class". In fact, prototype.js does.) See the next.

var Person = function(name){this.name = name;}; // constructor
// name is already defined in the constructor. 
Person.prototype.eat = function(){alert("Delicious!");};
Person.prototype.whoami = function(){alert(this.name);};
var person = new Person("hoge");
alert(person.name);
person.eat();

"this." in the constructor may look same with "prototype." Thus, you may want to use only "this." to define member methods and variables so that you can define everything in one place. It would look similar with class definitions in the other languages.

function Person(name) 
{
    this.name = name;
    this.eat = function(){
         alert("Delicious!");
    };
    this.whoami = function(){
         alert(this.name);
    };
}
var person = new Person("hoge");
alert(person.name);
person.eat();

However, "this." and "prototype." are different. "this." allocate memory spaces for each object. Therefore, eat() and whoami() functions are recreated in each object although they are same.

If we define them in prototype, object shares the definition (reference). What "new" does is that person.__proto__ = Person.prototype, and call the constructor. Javascript passes objects by reference, so person.__proto__ refers Person.prototype and person2.__proto__ also refers Person.prototype.

We can override member methods and variables in each object.

var Person = function(name){this.name = name;};
Person.prototype = {
    eat : function(){alert("Delicious!");},
    whoami : function(){alert(this.name);},
};
var person = new Person("hoge");
person.eat = function(){alert("Bad Taste!");}
person.eat(); // Bad Taste!
var person2 = new Person("hoge");
person2.eat(); // Delicious!

Think javascript chains searching as object.varname -> object.__proto__.varname -> object.__proto__.__proto__.varname-> ... up to root (Object prototype). This is like "extends" in the other languages (override).

I personally want to define everything in one place including a constructor. Fortunately, prototype.js has a trick for us.

var Person = Class.create();
Person.prototype = {
    name : "",
    height : null,
    initialize : function(name){this.name = name;},
    eat : function(){alert("Delicious!");},
    whoami : function(){alert(this.name);},
}
var person = new Person("foo");
var person2 = new Person("bar");

"initialize" work as a constructor.