JavaScript

Sarkuya,

JavaScript DOM

Table DOM

属性

table有以下主要通用属性:

  • childElementCount
  • childNodes
  • children
  • dataset: 所有以"data-"为先的命名属性的集合
  • isContentEditable
  • firstChild
  • firstElementChild
  • lastChild
  • lastElementChild
  • nextElementSibling
  • nextSibling
  • parentElement
  • parentNode
  • previousElementSibling
  • previousSibling

table有以下主要属性:

  • caption
  • rows: HTMLCollection
  • tHead
  • tBodies: HTMLCollection
  • tFoot

tHead, tFoot有以下属性:

  • rows: HTMLCollection, 返回[<tr>]

可以有多个tBody,因此,如果要访问第一个tBody,可使用tBodies[0]的方法来引用。每个tBody均有一个rows的属性。

tr有一个属性,cells[]。用以访问单元格,即th, 或td。

应对HTML元素

CSS属性

可使用以下方法应对CSS属性:

  1. element.getAttribute(attributeName)
  2. element.setAttribute(attributeName, value)
  3. element.removeAttribute(attributeName)
  4. element.style.getPropertyValue(propertyName)
  5. element.style.setProperty(propertyName, value)
  6. element.style.removePropertyValue(propertyName)
  7. element.style.cssText

事件

DOMContentLoaded

window.addEventListener("DOMContentLoaded", (event) => {
    console.log("Dom fully loaded and parsed");
});

内联与外联JavaScript是否允许相同函数名

html文件:

<script src="service.js"></script>

<script type="text/javascript">
    window.addEventListener("DOMContentLoaded", (event) => {
        console.log("in html...");
    });
</script>

外部的service.js文件:

window.addEventListener("DOMContentLoaded", (event) => {
    console.log("in js...");
});

运行结果:

in js...
in html...

说明尽管在两个地方都有相同的函数名,但都依调用次序先后得到执行。因此,内联与外联的JavaScript允许包含相同的函数名称。至于哪个先运行,取决于在代码中的先后次序。

读写CSS

document has a property named "styleSheets", holding the inline css rules and outer css rules.

Examples:

Suppose there is an outer css and an inline css in a HTML file. The following code get the inline one.

var innerCSS;

for (var i = 0; i < document.styleSheets.length; i++) {
    var ss = document.styleSheets[i];
    if (!ss.href) {
        innerCSS = ss;
        break;
    }
}

Now suppose the inline style has the content:

<style>
    #grid {
        background-color: lightgreen;
        display: grid;
        grid-template-columns: 100px 100px 100px;
        grid-gap: 10px;
    }

    #grid div {
        background-color: #ddd;
        border: 1px solid gray;
        border-radius: 5px;
        text-align: center;
    }
</style>

There are 2 css rules in it. The first is "#grid", and the second is "#grid div". Iterate each css rule:

for (var i = 0; i < innerCSS.cssRules.length; i ++) {
    var rule = innerCSS.cssRules[i];

    console.log(rule);
}

CSSStyleSheet

has the following properties:

cssRules
CSSRuleList, which has a function: item([index]), and a property: "length"
Each css rule in it is of type CSSStyleRule.
disabled
bbb
href
for the outer css style sheet, such as "css/style.css"
media
bbb
ownerNode
for outer css style sheet, nodeName is "LINK"
for inline css style sheet, nodeName is "STYLE"
ownerRule
bbb
parentStyleSheet
bbb
rules
bbb
title
bbb
type
"text/css"

CSSStyleRule

cssText
string representation of css content
parentRule
null
parentStyleSheet
bbb
selectorText
"#grid"
style
CSSStyleDeclaration
type
1

For example, for the following css:

.container {
    color: red;
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-gap: 10px;
}

The whole is a CSSStyleRule. Its' selectorText is ".container".

For the style, the contents are:

0: "background-color"
1: "display"
2: "grid-template-columns"
3: "grid-row-gap"
4: "grid-column-gap"
alignContent: ""
alignItems: ""
...
display: "grid"
...
gridTemplateColumns: "100px 100px 100px"

...

length: 5
...
x: ""
y: ""
zIndex: ""
zoom: ""

That means, the rule you added are shown as properties starting from 0.

Note that you specified the "grid-gap" property, while the style has the properties of "grid-row-gap" and "grid-column-gap", which means "grid-gap" is the shortcut for both of "grid-row-gap" and "grid-column-gap".

ECMAScript6新特性

lambda表达式

设有:

window.addEventListener("load", function() {
    console.log("Hello");
});

使用ECMAScript6,可改写为:

window.addEventListener("load", () => {
    console.log("Hello");
});

即使没有参数传入,这里的括号也不能省略。

如果匿名函数内只有一条语句,更可写为:

window.addEventListener("load", () => console.log("Hello"));

注意,此时这条单独的语句后面不能带有";"号。

如果有参数,

[1, 2, 3].forEach((element) => {
    console.log(element);
});

此时参数列表中的括号可以省略。

[1, 2, 3].forEach(element => {
    console.log(element);
});

可使用变量的字符串

使用`包围起来的字符串,可以在里面使用变量。

var result = 25;
var str = `结果为${result}。`

AJAX

fetch("test.json")
    .then(res => res.json())
    .then(data => {
        console.log(data.name);
    });

JSONP

像调用本地的JavaScript脚本一样,跨域调用远程服务器的JavaScript脚本,以获得服务器返回的数据。

本地调用JavaScript脚本

设有一test.html文件,内容为:

<script type="text/javascript">
    $(init);

    function init() {
        service();
    }

    function service() {
        doJob();
    }

    function doJob() {
        console.log("Doing job...");
    }
</script>

分离service函数

新建一个service.js文件,内容为:

function service() {
    doJob();
}

test.html的内容修改如下:

<script src="service.js"></script>

<script type="text/javascript">
    $(init);

    function init() {
        service();
    }

    function doJob() {
        console.log("Doing job...");
    }
</script>

加载service.js脚本文件,然后继续调用service()函数。此时,该函数已位于本地服务器中。

不用再调用service()函数

从提供服务的角度,我们可以不用再在脚本中调用service(),只需加载service.js就行了。

test.html的内容:

<html>
    <head>
        <script type="text/javascript">
            function doJob() {
                console.log("Doing job...");
            }
        </script>
    </head>
    <body>
        <script src="service.js"></script>
    </body>
</html>

service.js的内容:

doJob();

先定义好doJob()函数的内容,然后,在body中加载service.js文件,由于它直接调用了doJob()函数,此时,此函数已在本地中定义,将执行本地的doJob()函数。

这说明了什么问题?重温这句话:JavaScript是客户端的脚本语言。当我们"调用"service.js时,即使该文件就在服务器端,但服务器并不会在服务器端执行该文件。相反,服务器将返回该文件的全部内容至客户端,然后,在客户端才执行这个脚本文件的命令。

为什么这种方法能允许跨域运行?因为JavaScript是客户端的脚本语言,它只会在客户端运行,不存在攻击服务器的安全问题。

接收服务器数据

service.js的内容改为:

var data = {
    name: "Mike",
    age: 25
};

doJob(data);

test.html的内容改为:

function doJob(data) {
    console.log(data);
}

service.js先创建了一个data对象,然后,再以data为参数,调用doJob()函数。

慢着,service.js不是客户端的脚本语言吗,不是只能在客户端运行吗,即使返回data,此数据也是客户端的数据啊?

既正确,也不正确。service.js确实是客户端的脚本语言,上面的代码确实是在客户端生成的data,这一点很正确。但是,别忘了,service.js是存放在服务器端的文件。如果我们将这个JavaScript客户端脚本文件改为服务器端的脚本文件,如service.php, servcie.asp,等,它们不就可以有权限来访问服务器商的资源了吗?访问服务器端的资源文件,以生成data,然后,再写成客户端脚本可运行的doJob(data)的形式,以返回给客户端,其将在客户端中得以运行。就这么简单。

为简单起见,以使我们更关注JSONP的工作机制,本文中还是继续假设service.js是能取得服务器数据的脚本。

协议握手

上面service.js中要求客户端必须要有doJob()函数,才能将data接收回来。

aaa

aaa

aaa

aaa

aaa

相对路径的指定

每个文件均有一个所在的路径。这个文件的父路径不是这个所在的路径。

如果programming.html要引用cirecle.png, 则引用的相对路径为:

../../images/circle.png

第一个父路径为"html",第二个父路径为"root","images"为"root"的子路径。

参考资料

本地资源

网络资源

  1. CSS3实现32种基本图形
  2. CSS Zen Garden
  3. MDN Learn to sytle HTML using CSS
  4. CSS3样式生成器-Css3演示
  5. CSS速查总表
  6. CSS3实现的Tab Demo
  7. A List Apart
  8. Grid by Exmaple
  9. ECMAScript6 New Features
  10. Pure CSS responsive "Fork me on GitHub" ribbon
  11. ECMAScript 2015 Language Specification (ECMA-262, 6th Edition)
  12. JavaScript读写二进制数据