Changeset 17674 for docs

Show
Ignore:
Timestamp:
08/15/08 21:10:02 (3 months ago)
Author:
amachang
Message:

上級編と IE への対応方法を追加

Location:
docs/amachang/20080813-procamp2008
Files:
1 added
1 modified

Legend:

Unmodified
Added
Removed
  • docs/amachang/20080813-procamp2008/index.html

    r17619 r17674  
    14511451            </div> 
    14521452 
    1453  
     1453            <div> 
     1454                <h2>よりディープな JavaScript の世界へ</h2> 
     1455                <p> 
     1456                    テトリスがさっさと完成しちゃったっていう人に送る、よりディープな JavaScript の世界を紹介したいと思います。 
     1457                </p> 
     1458                <p> 
     1459                    完成したテトリスのコードを、より JavaScript 的に書き換えてみましょう! 
     1460                </p> 
     1461 
     1462                <div> 
     1463                    <h3>関数の名前は、関数という値が入った変数名</h3> 
     1464<pre><code>function hoge() { 
     1465    alert(1); 
     1466} 
     1467 
     1468hoge(); 
     1469</code></pre> 
     1470                    <p> 
     1471                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1472                    </p> 
     1473 
     1474                    <p> 
     1475                        この関数宣言は、実際には以下のようなことが行われています。 
     1476                    </p> 
     1477<pre><code>var hoge = function () { 
     1478    alert(1); 
     1479}; 
     1480 
     1481hoge(); 
     1482</code></pre> 
     1483                    <p> 
     1484                        実は、この書き方こそが本質的な JavaScript の関数の作りかたなのです。 
     1485                        今までの書き方は、これの簡易記法に過ぎません。 
     1486                    </p> 
     1487                    <p> 
     1488                        試しにさっきのコードを書き換えてみましょう! 
     1489                    </p> 
     1490 
     1491                    <p> 
     1492                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1493                    </p> 
     1494 
     1495<pre><code>&lt;!DOCTYPE html&gt; 
     1496&lt;html&gt; 
     1497    &lt;head&gt; 
     1498        &lt;meta charset=utf-8&gt; 
     1499        &lt;title&gt;Sample&lt;/title&gt; 
     1500        &lt;script type="text/javascript"&gt; 
     1501            var ctx; 
     1502            var blocks = [ 
     1503                [ 
     1504                    [1,1], 
     1505                    [0,1], 
     1506                    [0,1] 
     1507                ], 
     1508                [ 
     1509                    [1,1], 
     1510                    [1,0], 
     1511                    [1,0] 
     1512                ], 
     1513                [ 
     1514                    [1,1], 
     1515                    [1,1] 
     1516                ], 
     1517                [ 
     1518                    [1,0], 
     1519                    [1,1], 
     1520                    [1,0] 
     1521                ], 
     1522                [ 
     1523                    [1,0], 
     1524                    [1,1], 
     1525                    [0,1] 
     1526                ], 
     1527                [ 
     1528                    [0,1], 
     1529                    [1,1], 
     1530                    [1,0] 
     1531                ], 
     1532                [ 
     1533                    [1], 
     1534                    [1], 
     1535                    [1], 
     1536                    [1] 
     1537                ] 
     1538            ]; 
     1539 
     1540            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     1541            var posx = 0, posy = 0; 
     1542            var map, mapWidth = 10, mapHeight = 20; 
     1543 
     1544            <strong>var load = function() {</strong> 
     1545                var elmTarget = document.getElementById('target'); 
     1546                ctx = elmTarget.getContext('2d'); 
     1547 
     1548                map = []; 
     1549                for (var y = 0; y &lt; mapHeight; y++) { 
     1550                    map[y] = []; 
     1551                    for (var x = 0; x &lt; mapWidth; x++) { 
     1552                        map[y][x] = 0; 
     1553                    } 
     1554                } 
     1555                setInterval(paint, 200); 
     1556            <strong>};</strong> 
     1557 
     1558            <strong>var paintMatrix = function(matrix, offsetx, offsety, color) {</strong> 
     1559                ctx.fillStyle = color; 
     1560                for (var y = 0; y &lt; matrix.length; y ++) { 
     1561                    for (var x = 0; x &lt; matrix[y].length; x ++) { 
     1562                        if (matrix[y][x]) { 
     1563                            ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20); 
     1564                        } 
     1565                    } 
     1566                } 
     1567            <strong>};</strong> 
     1568 
     1569            <strong>var check = function(map, block, offsetx, offsety) {</strong> 
     1570                if (offsetx &lt; 0 || offsety &lt; 0 || 
     1571                    mapHeight &lt; offsety + block.length || 
     1572                    mapWidth &lt; offsetx + block[0].length) { 
     1573                    return false; 
     1574                } 
     1575                for (var y = 0; y &lt; block.length; y ++) { 
     1576                    for (var x = 0; x &lt; block[y].length; x ++) { 
     1577                        if (block[y][x] &amp;&amp; map[y + offsety][x + offsetx]) {  
     1578                            return false; 
     1579                        } 
     1580                    } 
     1581                } 
     1582                return true; 
     1583            <strong>};</strong> 
     1584 
     1585            <strong>var mergeMatrix = function(map, block, offsetx, offsety) {</strong> 
     1586                for (var y = 0; y &lt; mapHeight; y ++) { 
     1587                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1588                        if (block[y - offsety] &amp;&amp; block[y - offsety][x - offsetx]) { 
     1589                            map[y][x]++; 
     1590                        } 
     1591                    } 
     1592                } 
     1593            <strong>};</strong> 
     1594 
     1595            <strong>var clearRows = function(map) {</strong> 
     1596                for (var y = 0; y &lt; mapHeight; y ++) { 
     1597                    var full = true; 
     1598                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1599                        if (!map[y][x]) { 
     1600                            full = false; 
     1601                        } 
     1602                    } 
     1603                    if (full) { 
     1604                        map.splice(y, 1); 
     1605                        var newRow = []; 
     1606                        for (var i = 0; i &lt; mapWidth; i ++) { 
     1607                            newRow[i] = 0; 
     1608                        } 
     1609                        map.unshift(newRow); 
     1610                    } 
     1611                } 
     1612            <strong>};</strong> 
     1613 
     1614            <strong>var paint = function() {</strong> 
     1615                ctx.clearRect(0, 0, 200, 400); 
     1616                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     1617                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     1618 
     1619                if (check(map, block, posx, posy + 1)) { 
     1620                    posy = posy + 1; 
     1621                } 
     1622                else { 
     1623                    mergeMatrix(map, block, posx, posy); 
     1624                    clearRows(map); 
     1625                    posx = 0; posy = 0; 
     1626                    block = blocks[Math.floor(Math.random() * blocks.length)]; 
     1627                } 
     1628            <strong>};</strong> 
     1629 
     1630            <strong>var rotate = function(block) {</strong> 
     1631                var rotated = []; 
     1632                for (var x = 0; x &lt; block[0].length; x ++) { 
     1633                    rotated[x] = []; 
     1634                    for (var y = 0; y &lt; block.length; y ++) { 
     1635                        rotated[x][block.length - y - 1] = block[y][x]; 
     1636                    } 
     1637                } 
     1638                return rotated; 
     1639            <strong>};</strong> 
     1640 
     1641            <strong>var key = function(keyCode) {</strong> 
     1642                switch (keyCode) { 
     1643                    case 38: 
     1644                        if (!check(map, rotate(block), posx, posy)) { 
     1645                            return; 
     1646                        } 
     1647                        block = rotate(block); 
     1648                        break; 
     1649                    case 39: 
     1650                        if (!check(map, block, posx + 1, posy)) { 
     1651                            return; 
     1652                        } 
     1653                        posx = posx + 1; 
     1654                        break; 
     1655                    case 37: 
     1656                        if (!check(map, block, posx - 1, posy)) { 
     1657                            return; 
     1658                        } 
     1659                        posx = posx - 1; 
     1660                        break; 
     1661                    case 40: 
     1662                        var y = posy; 
     1663                        while (check(map, block, posx, y)) { y++; } 
     1664                        posy = y - 1; 
     1665                        break; 
     1666                    default: 
     1667                        return; 
     1668                } 
     1669                ctx.clearRect(0, 0, 200, 400); 
     1670                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     1671                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     1672            <strong>};</strong> 
     1673 
     1674        &lt;/script&gt; 
     1675    &lt;/head&gt; 
     1676 
     1677    &lt;body onload="load()" onkeydown="key(event.keyCode)"&gt; 
     1678        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     1679    &lt;/body&gt; 
     1680&lt;/html&gt;</code></pre> 
     1681                    <p> 
     1682                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     1683                    </p> 
     1684 
     1685                </div> 
     1686 
     1687                <div> 
     1688                    <h3>関数は、関数に渡せる</h3> 
     1689                    <p> 
     1690                        前の項で、関数は変数に代入可能な値というのが分かりました。 
     1691                    </p> 
     1692                    <p> 
     1693                        変数に代入可能な値は、関数にも渡すことができます。 
     1694                    </p> 
     1695                    <p> 
     1696                        実は、今までの例でも関数に関数を渡している箇所があります。 
     1697                        そうです。 paint 関数を定期的に呼び出すところですね。 
     1698                    </p> 
     1699                    <p> 
     1700                        以下のような例は setInterval という関数に hoge という関数を渡しているのですね。 
     1701                    </p> 
     1702<pre><code>var hoge = function() { 
     1703    alert(1); 
     1704}; 
     1705 
     1706// 3 秒に一回 hoge を呼び出す 
     1707setInterval(hoge, 3000); 
     1708</code></pre> 
     1709                    <p> 
     1710                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1711                    </p> 
     1712                    <p> 
     1713                        もちろん、変数に一回代入しなくても、直接関数を渡すことができます。 
     1714                    </p> 
     1715<pre><code>setInterval(function() { 
     1716    alert(1); 
     1717}, 3000); 
     1718</code></pre> 
     1719                    <p> 
     1720                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1721                    </p> 
     1722 
     1723                    <p> 
     1724                        では、テトリスのコードも直接関数を渡す形式に書き換えてみましょう! 
     1725                        (paint 関数の中身を直接 setInterval にぶち込みます) 
     1726                    </p> 
     1727<pre><code>&lt;!DOCTYPE html&gt; 
     1728&lt;html&gt; 
     1729    &lt;head&gt; 
     1730        &lt;meta charset=utf-8&gt; 
     1731        &lt;title&gt;Sample&lt;/title&gt; 
     1732        &lt;script type="text/javascript"&gt; 
     1733            var ctx; 
     1734            var blocks = [ 
     1735                [ 
     1736                    [1,1], 
     1737                    [0,1], 
     1738                    [0,1] 
     1739                ], 
     1740                [ 
     1741                    [1,1], 
     1742                    [1,0], 
     1743                    [1,0] 
     1744                ], 
     1745                [ 
     1746                    [1,1], 
     1747                    [1,1] 
     1748                ], 
     1749                [ 
     1750                    [1,0], 
     1751                    [1,1], 
     1752                    [1,0] 
     1753                ], 
     1754                [ 
     1755                    [1,0], 
     1756                    [1,1], 
     1757                    [0,1] 
     1758                ], 
     1759                [ 
     1760                    [0,1], 
     1761                    [1,1], 
     1762                    [1,0] 
     1763                ], 
     1764                [ 
     1765                    [1], 
     1766                    [1], 
     1767                    [1], 
     1768                    [1] 
     1769                ] 
     1770            ]; 
     1771 
     1772            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     1773            var posx = 0, posy = 0; 
     1774            var map, mapWidth = 10, mapHeight = 20; 
     1775 
     1776            var load = function() { 
     1777                var elmTarget = document.getElementById('target'); 
     1778                ctx = elmTarget.getContext('2d'); 
     1779 
     1780                map = []; 
     1781                for (var y = 0; y &lt; mapHeight; y++) { 
     1782                    map[y] = []; 
     1783                    for (var x = 0; x &lt; mapWidth; x++) { 
     1784                        map[y][x] = 0; 
     1785                    } 
     1786                } 
     1787 
     1788                <strong>setInterval(function() {</strong> 
     1789                    <strong>ctx.clearRect(0, 0, 200, 400);</strong> 
     1790                    <strong>paintMatrix(block, posx, posy, 'rgb(255, 0, 0)');</strong> 
     1791                    <strong>paintMatrix(map, 0, 0, 'rgb(128, 128, 128)');</strong> 
     1792 
     1793                    <strong>if (check(map, block, posx, posy + 1)) {</strong> 
     1794                        <strong>posy = posy + 1;</strong> 
     1795                    <strong>}</strong> 
     1796                    <strong>else {</strong> 
     1797                        <strong>mergeMatrix(map, block, posx, posy);</strong> 
     1798                        <strong>clearRows(map);</strong> 
     1799                        <strong>posx = 0; posy = 0;</strong> 
     1800                        <strong>block = blocks[Math.floor(Math.random() * blocks.length)];</strong> 
     1801                    <strong>}</strong> 
     1802                <strong>}, 200);</strong> 
     1803            }; 
     1804 
     1805            var paintMatrix = function(matrix, offsetx, offsety, color) { 
     1806                ctx.fillStyle = color; 
     1807                for (var y = 0; y &lt; matrix.length; y ++) { 
     1808                    for (var x = 0; x &lt; matrix[y].length; x ++) { 
     1809                        if (matrix[y][x]) { 
     1810                            ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20); 
     1811                        } 
     1812                    } 
     1813                } 
     1814            }; 
     1815 
     1816            var check = function(map, block, offsetx, offsety) { 
     1817                if (offsetx &lt; 0 || offsety &lt; 0 || 
     1818                    mapHeight &lt; offsety + block.length || 
     1819                    mapWidth &lt; offsetx + block[0].length) { 
     1820                    return false; 
     1821                } 
     1822                for (var y = 0; y &lt; block.length; y ++) { 
     1823                    for (var x = 0; x &lt; block[y].length; x ++) { 
     1824                        if (block[y][x] &amp;&amp; map[y + offsety][x + offsetx]) {  
     1825                            return false; 
     1826                        } 
     1827                    } 
     1828                } 
     1829                return true; 
     1830            }; 
     1831 
     1832            var mergeMatrix = function(map, block, offsetx, offsety) { 
     1833                for (var y = 0; y &lt; mapHeight; y ++) { 
     1834                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1835                        if (block[y - offsety] &amp;&amp; block[y - offsety][x - offsetx]) { 
     1836                            map[y][x]++; 
     1837                        } 
     1838                    } 
     1839                } 
     1840            }; 
     1841 
     1842            var clearRows = function(map) { 
     1843                for (var y = 0; y &lt; mapHeight; y ++) { 
     1844                    var full = true; 
     1845                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1846                        if (!map[y][x]) { 
     1847                            full = false; 
     1848                        } 
     1849                    } 
     1850                    if (full) { 
     1851                        map.splice(y, 1); 
     1852                        var newRow = []; 
     1853                        for (var i = 0; i &lt; mapWidth; i ++) { 
     1854                            newRow[i] = 0; 
     1855                        } 
     1856                        map.unshift(newRow); 
     1857                    } 
     1858                } 
     1859            }; 
     1860 
     1861            var rotate = function(block) { 
     1862                var rotated = []; 
     1863                for (var x = 0; x &lt; block[0].length; x ++) { 
     1864                    rotated[x] = []; 
     1865                    for (var y = 0; y &lt; block.length; y ++) { 
     1866                        rotated[x][block.length - y - 1] = block[y][x]; 
     1867                    } 
     1868                } 
     1869                return rotated; 
     1870            }; 
     1871 
     1872            var key = function(keyCode) { 
     1873                switch (keyCode) { 
     1874                    case 38: 
     1875                        if (!check(map, rotate(block), posx, posy)) { 
     1876                            return; 
     1877                        } 
     1878                        block = rotate(block); 
     1879                        break; 
     1880                    case 39: 
     1881                        if (!check(map, block, posx + 1, posy)) { 
     1882                            return; 
     1883                        } 
     1884                        posx = posx + 1; 
     1885                        break; 
     1886                    case 37: 
     1887                        if (!check(map, block, posx - 1, posy)) { 
     1888                            return; 
     1889                        } 
     1890                        posx = posx - 1; 
     1891                        break; 
     1892                    case 40: 
     1893                        var y = posy; 
     1894                        while (check(map, block, posx, y)) { y++; } 
     1895                        posy = y - 1; 
     1896                        break; 
     1897                    default: 
     1898                        return; 
     1899                } 
     1900                ctx.clearRect(0, 0, 200, 400); 
     1901                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     1902                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     1903            }; 
     1904 
     1905        &lt;/script&gt; 
     1906    &lt;/head&gt; 
     1907 
     1908    &lt;body onload="load()" onkeydown="key(event.keyCode)"&gt; 
     1909        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     1910    &lt;/body&gt; 
     1911&lt;/html&gt;</code></pre> 
     1912                    <p> 
     1913                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     1914                    </p> 
     1915                </div> 
     1916 
     1917                <div> 
     1918                    <h3>オブジェクトを作ってみよう</h3> 
     1919 
     1920                    <p> 
     1921                        今までに出てきた ctx などのような<strong>値の中にさらに値(関数も含む)を持つ値</strong>のことを 
     1922                        <strong>オブジェクト</strong>と言います。 
     1923                    </p> 
     1924 
     1925                    <p> 
     1926                        さっそく、オブジェクトを作ってみましょう。 
     1927                    </p> 
     1928<pre><code>var a = { 
     1929    hoge: 1, 
     1930    fuga: 2 
     1931}; 
     1932 
     1933alert(a.hoge); 
     1934alert(a.fuga); 
     1935</code></pre> 
     1936                    <p> 
     1937                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1938                    </p> 
     1939                    <p> 
     1940                        ここでの hoge や fuga のことをプロパティといいます。 
     1941                    </p> 
     1942 
     1943                    <p> 
     1944                        プロパティには、値を代入することもできます。 
     1945                    </p> 
     1946<pre><code>var a = { 
     1947    hoge: 1, 
     1948    fuga: 2 
     1949}; 
     1950 
     1951a.hoge = 3; 
     1952 
     1953alert(a.hoge); 
     1954</code></pre> 
     1955                    <p> 
     1956                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1957                    </p> 
     1958 
     1959                    <p> 
     1960                        存在しないプロパティに値を代入することもできます。 
     1961                    </p> 
     1962<pre><code>var a = { 
     1963    hoge: 1, 
     1964    fuga: 2 
     1965}; 
     1966 
     1967a.piyo = 3; 
     1968 
     1969alert(a.piyo); 
     1970</code></pre> 
     1971                    <p> 
     1972                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1973                    </p> 
     1974 
     1975                    <p> 
     1976                        関数をプロパティに持たせることもできます。 
     1977                        このときに this という特殊な変数なようなものを使うと、そのオブジェクト自体を関数内で扱うことが出来ます。 
     1978                    </p> 
     1979<pre><code>var a = { 
     1980    hoge: 1, 
     1981    fuga: 2, 
     1982    alertHoge: function() { 
     1983        alert(this.hoge); 
     1984    } 
     1985}; 
     1986 
     1987a.alertHoge(); 
     1988</code></pre> 
     1989                    <p> 
     1990                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1991                    </p> 
     1992 
     1993                    <p> 
     1994                        このように、<strong>値に対する様々な操作</strong>はオブジェクトにプロパティに入れた関数で行うと、 
     1995                        プログラム全体の見通しがよくなります。 
     1996                    </p> 
     1997 
     1998                </div> 
     1999 
     2000                <div> 
     2001                    <h3>同じ特性を持ったオブジェクトを作る</h3> 
     2002                    <p> 
     2003                        プログラムをやっていると、同じ特性を持ったオブジェクトを作りたいという時があります。 
     2004                        そのようなときは new という仕組みを使います。 
     2005                    </p> 
     2006 
     2007<pre><code>var Dog = function(name) { 
     2008    this.name = name; 
     2009    this.type = '犬'; 
     2010}; 
     2011 
     2012var pochi = new Dog('ポチ'); 
     2013var hachi = new Dog('ハチ'); 
     2014 
     2015alert(pochi.name); 
     2016alert(pochi.type); 
     2017 
     2018alert(hachi.name); 
     2019alert(hachi.type); 
     2020</code></pre> 
     2021                    <p> 
     2022                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     2023                    </p> 
     2024 
     2025                    <p> 
     2026                        ちょっと変な感じがするかもしれませんが、関数には二つの使い方があるのです。 
     2027                    </p> 
     2028                    <ul> 
     2029                        <li>処理をまとめる(普通の関数として使う)</li> 
     2030                        <li>同じ特性を持ったオブジェクトを生成する</li> 
     2031                    </ul> 
     2032                    <p> 
     2033                        この 2 番目の使い方をする関数のことを<strong>コンストラクタ</strong>といいます。 
     2034                    </p> 
     2035                    <p> 
     2036                        このように関数と new を使ってオブジェクトを作った場合は、全員に共通のプロパティを持たせることができます。 
     2037                    </p> 
     2038                    <p> 
     2039                        以下の例をみてみましょう。 
     2040                    </p> 
     2041 
     2042<pre><code>var Dog = function(name) { 
     2043    this.name = name; 
     2044}; 
     2045 
     2046<strong>Dog.prototype.type = '犬';</strong> 
     2047<strong>Dog.prototype.bow = function() {</strong> 
     2048    <strong>alert(this.name + '「わんわん」');</strong> 
     2049<strong>};</strong> 
     2050 
     2051var pochi = new Dog('ポチ'); 
     2052var hachi = new Dog('ハチ'); 
     2053 
     2054pochi.bow(); 
     2055hachi.bow(); 
     2056</code></pre> 
     2057                    <p> 
     2058                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     2059                    </p> 
     2060                    <p> 
     2061                        つまり pochi オブジェクトや hachi オブジェクトは 
     2062                        Dog.prototype オブジェクトが持っている全てのプロパティにアクセスすることができます。 
     2063                    </p> 
     2064                    <p> 
     2065                        このとき、 pochi オブジェクトや hachi オブジェクトは、 Dog.prototype オブジェクトを<strong>継承</strong>したオブジェクトといいます。 
     2066                    </p> 
     2067                </div> 
     2068 
     2069                <div> 
     2070                    <h3>配列が継承しているオブジェクト</h3> 
     2071                    <p> 
     2072                        このように、オブジェクトはオブジェクトを継承することで、共通のプロパティを作ることができます。 
     2073                    </p> 
     2074                    <p> 
     2075                        実は、配列も <strong>Array.prototype</strong> というオブジェクトを継承しています。 
     2076                    </p> 
     2077                    <p> 
     2078                        以下の例を見てみましょう。 
     2079                    </p>