前端-书籍推荐

由于曾经在高中买来《C Primer Plus》和大学买来的《Clean Code》(挑战本身买的英文版的结果就啃了一点)给我一种经典的书都特别厚的一本就够读大半年的感受。加上刚上大学图便宜买的有关作网站的旧书(应该是 Table 布局和 Dreamweaver 比较火的时代的书,这些书却是很薄)让我一度认为作网页不就是 table 而后 tr、td 什么的套呗,高大上点不就是 div+CSS 嘛有什么大不了,给我设计好什么网页不都 ok 能作出来么?这种感受。而后看网络课程,在网上找资料学习后才发现之前的本身太逗了,以后就一直靠网络课程、MDN、博客、百科这些渠道学习,但一想到网上大牛们评价特别高的书还没看过就总感受少了点什么。最近将这些书看了看,发现之前只知道要这么作比较好的地方如今也更加明白这样作的意义,也纠正了之前理解的一些错误。javascript

我这里我只总结一些我之前掌握不扎实的和我认为比较重要的。php

JavaScript 高级程序设计

第 3 章 基本概念

3.5.2 位操做符

ECMAScript 中全部数值都是以 IEEE-754 64 位格式存储,但位操做符并不直接操做 64 位的值。而是先将 64 位的值转换成 32 位的整数,而后执行操做,最后再将结果转换为 64 位。(对于开发人员 64 位存储格式是透明的,所以整个过程像是只存在 32 位的整数同样)css

3.5.6 关系操做符

  • 比较的操做数为对象,则调用 valueOf() 方法(没有 valueOf() 调用 toString() 方法),用获得的值进行比较
  • 比较的操做数为布尔值,则转换为数字比较

3.7.1 理解参数

  • 修改 arguments 数组会改变形参的值(这并非说它们访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。好比未传入形参时,修改了 arguments 数组形参值也不会变)
function func(para1, para2){
  console.log('修改前', arguments , para1, para2);
  arguments [0] = 'arguements_0';
  arguments [1] = 'arguements_1';
  console.log('修改后', arguments , para1, para2);
}
func('para1')
  • arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。
  • ECMAScript 中的参数都是值传递,不存在引用传递

第 4 章 变量、做用域和内存问题

4.1 基本类型和引用类型的值

基本类型:html

  1. Undefined
  2. Null
  3. Boolean
  4. Number
  5. String(注意 String 是基本类型)

基本类型的值没法添加属性(尽管这样不会报错),eg:前端

var name = "zhang";
name.age = 17;
console.log(name.age);// undefined

引用类型:html5

  1. Object

4.1.3 传递参数

ECMAScript 中全部函数的参数都是按值传递的。java

eg:这里的 obj 形参是建立了一个指针让他与 person 指针指向同一个地址,obj 和 person 都指向同一个地址,但改变 obj 的指向 person 不改变css3

function setName(obj) {
    obj.name = "Nicholas";
    obj = new Object();
    obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"

4.2.2 没有块级做用域

使用 var 声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境;在 with 语句中,最接近的环境是函数环境。若是初始化变量时没有使用 var 声明,该变量会自动被添加到全局环境。程序员

// 1.if
if (true) {
    var color = "blue";
}
alert(color); //"blue"

// 2.for
for (var i=0; i < 10; i++){
}
alert(i); //10

// 3.function
function add(num1, num2) {
    var sum = num1 + num2;
    return sum;
}
alert(sum); //因为 sum 不是有效的变量,所以会致使错误

如今使用 ES6 的let会声明块级做用域变量。web

4.3 垃圾收集

经常使用标记清除,不经常使用引用计数

第 5 章 引用类型

5.2 Array 类型

若是 slice() 方法的参数中有一个负数,则用数组长度加上该数来肯定相应的位置。例如,在一个包含 5 项的数组上调用 slice(-2,-1) 与调用 slice(3,4) 获得的结果相同。若是结束位置小于起始位置,则返回空数组。

5.2.8 迭代方法

  • every():对数组中的每一项运行给定函数,若是该函数对每一项都返回 true,则返回 true。
  • filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
  • forEach():对数组中的每一项运行给定函数。这个方法没有返回值。
  • map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
  • some():对数组中的每一项运行给定函数,若是该函数对任一项返回 true,则返回 true

5.2.9 归并方法

ECMAScript 5 还新增了两个归并数组的方法: reduce() 和 reduceRight()。这两个方法都会迭代数组的全部项,而后构建一个最终返回的值。其中, reduce() 方法从数组的第一项开始,逐个遍历到最后。而 reduceRight() 则从数组的最后一项开始,向前遍历到第一项。

第 6 章 面向对象的程序设计

6.1.1 属性类型

  1. 数据属性
  2. 访问器属性(VUE 双向绑定实现的基础)

6.2 建立对象

  1. 工厂模式(使用函数建立对象,为对象添加属性和方法而后返回对象,被构造函数模式取代)

    function createPersion(name, age) {
        return {
            name,
            age
        }
    }
    
    var p1 = createPersion("zhang", 17);
    var p2 = createPersion("foo", 18);
  2. 构造函数模式(每一个实例不共用属性和方法,JS 中函数是对象)

    function Persion(name, age) {
        this.name = name;
        this.age = age;
        this.print = function () {
            console.log(this.name);
        }
    }
    
    var p1 = new Persion("zhang", 17);
    var p2 = new Persion("foo", 18);
  3. 原型模式(每一个实例共用一套属性和方法)

    function Persion() {}
    Persion.prototype.name = "zhang";
    Persion.prototype.age = 17;
    Persion.prototype.print = function () {
        console.log(this.name);
    }
    
    var p1 = new Persion();
    var p2 = new Persion();
  4. 组合使用构造函数模式和原型模式(既有共用又有不共用的属性和方法)

    • 这是目前使用最普遍的建立自定义类型的方法。

    • 使用对象覆盖原型(字面量方式修改原型)要注意已经建立的实例的constructor指针不会自动变(仍是覆盖前的原型)。

    function Persion(name, age) {
        this.name = name;
        this.age = age;
    }
    Persion.prototype = {
        constructor: Persion,
        print: function () {
            console.log(this.name);
        }
    }
    
    var p1 = new Persion("zhang", 17);
    var p2 = new Persion("foo", 18);
  5. 动态原型模式(给原型添加属性的操做放到构造函数内)

    function Persion(name, age) {
        this.name = name;
        this.age = age;
        // 第一次执行时初始化
        if (typeof this, print !== "function") {
            Persion.prototype.print = function () {
                console.log(this.name);
            }
        }
    }
    
    var p1 = new Persion("zhang", 17);
    var p2 = new Persion("foo", 18);
  6. 寄生构造函数模式(和工厂模式几乎同样,能够为对象建立构造函数)

    function MyArray(){
        let arr = new Array();
        arr.push.apply(arr, arguments);
        arr.toPipeString = function(){
            return this.join("|");
        }
        return arr;
    }
    
    var marr = new MyArray(1,2,3);
    console.log(marr.toPipeString());
  7. 稳妥构造函数模式

    • 稳妥对象:没有公共属性,方法也不引用this对象。适合用在安全环境中,或防止数据被其余程序改动。
    function Persion(name, age) {
        var o = {};
    
        // 除了使用 print 没有其余方法能获取到 name
        o.print = function () {
            console.log(name);
        }
        return o;
    }
    
    var p1 = new Persion("zhang", 17);
    var p2 = new Persion("foo", 18);

6.3 继承

OO 语言支持两种继承:接口继承和实现继承。因为函数没有签名,ES 没法实现接口继承。

  1. 原型链(有两个问题:属性共享和参数传递)

    function SuperType(para) {
        this.property = true;
        this.arr = [1, 2, 3];
        this.para = para;
    }
    
    SuperType.prototype.getSuperProp = function () {
        return this.property;
    }
    
    function SubType() {
        this.subproperty = false;
    }
    
    // 继承(这时 SubType.prototype.constructor 属性没有了,SubType.[[prototype]].constructor 为 SuperType)
    SubType.prototype = new SuperType();
    
    SubType.prototype.getSubProp = function () {
        return this.subproperty;
    }
    
    // 问题1:没法向父类构造函数传值
    var instance1 = new SubType();
    var instance2 = new SubType();
    
    // 问题2:instance2.arr 也改变了
    instance1.arr.push(4);
  2. 借用构造函数(和构造函数的问题同样:每一个实例不共用属性和方法)

    function SuperType(para) {
        this.para = para;
        this.getPara = function(){
            return this.para;
        }
    }
    
    function SubType() {
        SuperType.apply(this, arguments);
    }
    
    // 能够向父类构造函数传值
    var instance1 = new SubType("instance1");
    var instance2 = new SubType("instance2");
  3. 组合继承(JS 中最经常使用的继承模式)

    function SuperType(para) {
        this.property = true;
        this.arr = [1, 2, 3];
        this.para = para;
    }
    
    SuperType.prototype.getSuperProp = function () {
        return this.property;
    }
    
    function SubType() {
        SuperType.apply(this, arguments);
        this.subproperty = false;
    }
    
    // 继承
    SubType.prototype = new SuperType();
    SubType.prototype.constructor = SubType;
    
    SubType.prototype.getSubProp = function () {
        return this.subproperty;
    }
    
    // 能够向父类构造函数传值
    var instance1 = new SubType("instance1");
    var instance2 = new SubType("instance2");
    
    // instance2.arr 不变
    instance1.arr.push(4);
  4. 原型式继承(Object.create()

    function createObj(obj) {
        function f() {};
        f.prototype = obj;
        return new f();
    }
    
    var person = {
        name: "zhang",
        age: [17]
    }
    
    // person、 zi 和 ma 共用引用属性 age
    var zi = createObj(person);
    var ma = createObj(person);
    
    zi.age.push(18);
    ma.age.push(17);
    console.log(person.age);
  5. 寄生式继承(和寄生构造函数相似)

    function createObjParasitic(obj) {
        let o = Object.create(obj);
        // o 目前是以下对象:
        // {
        //     [[prototype]] = obj
        // }
        o.sayHi = function () {
            console.log("hi")
        }
        return o;
    }
    
    var person = {
        name: "zhang",
        age: [17]
    }
    
    var zi = createObjParasitic(person);
    
    zi.sayHi();
  6. 寄生组合式继承(将new SuperType()改成Object.create(SuperType.prototype)减小一次父类的调用,还避免了在SubType上添加没必要要的属性)

    function inheritPrototype(sub, sup) {
        // 使 sub.prototype 的 [[prototype]] “指针”指向 sup.prototype
        sub.prototype = Object.create(sup.prototype);
        sub.prototype.constructor = sub;
    }
    
    function SuperType() {
        this.property = true;
        this.arr = [1, 2, 3];
    }
    
    SuperType.prototype.getSuperProp = function () {
        return this.property;
    }
    
    function SubType() {
        SuperType.apply(this, arguments);
        this.subproperty = false;
    }
    
    inheritPrototype(SubType, SuperType);
    
    console.log((new SubType()).getSuperProp());

第 7 章 函数表达式

定义函数有两种形式:函数声明(会函数声明提高)和函数表达式。

7.2 闭包

闭包指有权访问另外一个函数做用域中的变量的函数。

7.2.2 关于 this 对象

每一个函数在被调用时都会自动取得两个特殊变量: this 和 arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,所以永远不可能直接访问外部函数中的这两个变量。不过,把外部做用域中的 this 对象保存在一个闭包可以访问到的变量里,就可让闭包访问该对象了。

若是想访问做用域中的 this 和 arguments 对象必须把她们保存在闭包能够访问的变量中。

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function () {
        return function () {
            // this指向window
            return this.name;
        };
    }
};
console.log(object.getNameFunc()()); //"The Window"(在非严格模式下)

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function () {
        var that = this;
        return function () {
            // 闭包能够访问that
            // this指向window,that指向object
            return that.name;
        };
    }
};
console.log(object.getNameFunc()()); //"My Object"

7.4 私有变量

JS 中没有使用成员的概念,全部对象属性都是共有的。但在函数中定义的变量均可以认为是私有比阿尼浪,由于不能在函数外部访问这些变量(包括:参数、局部变量和函数内部定义的其余函数)。

7.4.2 模块模式

JS 以字面量的方式建立单例对象。

var singleton = {
    name: "xxx",
    method: function () {
        // ...
    }
}

7.4.3 加强的模块模式

// 这时 function(){...}() 是当作语句解析的
var application = function(){
    //私有变量和函数
    var components = new Array();
    //初始化
    components.push(new BaseComponent());
    //建立 application 的一个局部副本
    var app = new BaseComponent();
    //公共接口
    app.getComponentCount = function(){
        return components.length;
    };
    app.registerComponent = function(component){
        if (typeof component == "object"){
             components.push(component);
        }
    };
    //返回这个副本
    return app;
}();

第 8 章 BOM

8.1 window 对象

BOM 的核心是 window 对象,它表示浏览器的一个实例,同时也是 ES 中规定的 Global 对象。

8.1.2 窗口关系及框架

若是页面中包含框架,则每一个框架都拥有本身的 window 对象,而且保存在 frames 集合中。在 frames 集合中,能够经过数值索引(从 0 开始,从左至右,从上到下)或者框架名称来访问相应的 window 对象。每一个 window 对象都有一个 name 属性,其中包含框架的名称。

在使用框架的状况下,浏览器中会存在多个 Global 对象。在每一个框架中定义的全局变量会自动成为框架中 window 对象的属性。因为每一个 window 对象都包含原生类型的构造函数,所以每一个框架都有一套本身的构造函数,这些构造函数一一对应,但并不相等。例如,top.Object并不等于top.frames[0].Object。这个问题会影响到对跨框架传递的对象使用instanceof操做符。

  • window.top对象始终指向最外层框架,也就是浏览器窗口
  • window.parent指向父窗口
  • window.self指向 window

8.1.3 窗口位置

窗口相对屏幕的位置:window.screenLeftwindow.screenTop

窗口位置移动(默认是禁用的):window.moveTo()window.moveBy()

8.1.4 窗口大小

浏览器窗口大小(不一样浏览器对这些属性的解释不一样):window.innerHeightwindow.innerWidthwindow.outerWidthwindow.outerWidth

页面视口信息:window.document.documentElement.clientWidthwindow.document.documentElement.clientHeight

浏览器窗口大小改变(默认是禁用的):window.resizeTo()window.resizeBy()

8.1.6 间歇调用和超时调用

通常认为,使用超时调用来模拟间歇调用是一种最佳模式。在开发环境下,不多使用真正的间歇调用,缘由是后一个间歇调用可能会在前一个间歇调用结束以前启动。而像下面示例中那样使用超时调用,则彻底能够避免这一点。因此,最好不要使用间歇调用。

// 超时调用模拟间歇调用
var num = 0;
var max = 10;
function incrementNumber() {
    num++;
    //若是执行次数未达到 max 设定的值,则设置另外一次超时调用
    if (num < max) {
        setTimeout(incrementNumber, 500);
    } else {
        alert("Done");
    }
}
setTimeout(incrementNumber, 500);

8.2 location 对象

8.2.2 位置操做

// 基本
location.assign("https://developer.mozilla.org")
// 下面两种和和显示调用 assign 方法同样
window.location = "https://developer.mozilla.org"
location.href = "https://developer.mozilla.org"
// 其余
location.hash = "#123"
location.pathname = "zh-CN"
// replace 的 location 不记录在历史记录中
location.replace("https://developer.mozilla.org")

获取浏览器信息、主语言、插件、设置等信息。

8.4 screen 对象

用来获取浏览器窗口外部的显示器信息,如像素宽度、高度等。

8.5 history 对象

// 跳转到最近的 mdn 界面
history.go("developer.mozilla.org");

第 9 章 客户端检测

  • 能力(特性)检测:检测浏览器是否支持某项功能
function isHostMethod(object, property) {
    var t = typeof object[property];
    return t === 'function' || (!!(t === 'object' && object[property])) || t === 'unknown';
}
console.log(isHostMethod([], 'find'));
  • 怪癖检测:检测浏览器某项功能是否有 bug
// 是否有将属性不列举的bug
var hasDontEnumQuirk = function() {
    var o = {
        // 这里新的 toString 应该要列举出来的,由于新的 toString 已经覆盖了旧的 [[Enumerable]] false 的 toString
        // 但 IE8 及更低版本的浏览器会不将 toString 列举。
        toString: function () {}
    };
    for (var prop in o) {
        if (prop === 'toString') {
            return false;
        }
    }
    return true;
}();
console.log(hasDontEnumQuirk());
  • 用户代理检测:检测呈现引擎、浏览器、平台、设备和操做系统

    由于用户代理字符串有很长的发展历史,在此期间浏览器供应商试图在用户代理字符串中添加一些欺骗信息,让网站相信本身是另外一种浏览器,使得用户代理检测比较复杂。但经过navigator.userAgent(大部分信息在这个字符串中),navigator.platformwindow的属性仍是能够检测出来呈现引擎、浏览器、平台、设备和操做系统这些信息的。

第 10 章 DOM

10.1.8 DocumentFragment 类型

VUE 使用 DocumentFragment 优化 DOM 节点操做

在全部节点类型中,只有 DocumentFragment 在文档中没有对应的标记。 DOM 规定文档片断(document fragment)是一种 “轻量级” 的文档,能够包含和控制节点,但不会像完整的文档那样占用额外的资源。

第 11 章 DOM 扩展

11.3.2 焦点管理

HTML5 也添加了辅助管理 DOM 焦点的功能。首先就是 document.activeElement 属性,这个属性始终会引用 DOM 中当前得到了焦点的元素。元素得到焦点的方式有页面加载、用户输入(一般是经过按 Tab 键)和在代码中调用 focus() 方法。

11.3.5 自定义数据属性

HTML5 规定能够为元素添加非标准的属性,但要添加前缀 data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。这些属性能够任意添加、随便命名,只要以 data - 开头便可。

<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>

<script>
  //本例中使用的方法仅用于演示
  var div = document.getElementById("myDiv");
  //取得自定义属性的值
  var appId = div.dataset.appId;
  var myName = div.dataset.myname;
  //设置值
  div.dataset.appId = 23456;
  div.dataset.myname = "Michael";
  //有没有"myname"值呢?
  if (div.dataset.myname){
    alert("Hello, " + div.dataset.myname);
  }
</script>

第 12 章 DOM2 和 DOM3

DOM2 级和 3 级的目的在于扩展 DOM API,以知足操做 XML 的全部需求,同时提供更好的错误处理及特性检测能力。从某种意义上讲,实现这一目的很大程度意味着对命名空间的支持。“DOM2 级核心” 没有引入新类型,它只是在 DOM1 级的基础上经过增长新方法和新属性来加强了既有类型。“DOM3 级核心” 一样加强了既有类型,但也引入了一些新类型。

12.2.1 访问元素的样式

多数状况下,均可以经过简单地转换属性名的格式来实现转换。其中一个不能直接转换的 CSS 属性就是 float。因为 float 是 JavaScript 中的保留字,所以不能用做属性名。“DOM2 级样式” 规范规定样式对象上相应的属性名应该是 cssFloat; Firefox、 Safari、 Opera 和 Chrome 都支持这个属性,而 IE 支持的则是 styleFloat。

<div id="myDiv">myDiv</div>
<script>
    var myDiv = document.getElementById("myDiv");
    //浮动
    myDiv.style.cssFloat = "left";
    //背景颜色
    myDiv.style.backgroundColor = "red";
    //改变大小
    myDiv.style.width = "100px";
    myDiv.style.height = "200px";
    //指定边框
    myDiv.style.border = "1px solid black";
</script>

12.4 范围

为了让开发人员更方便地控制页面,“DOM2 级遍历和范围” 模块定义了 “范围”(range)接口。经过范围能够选择文档中的一个区域,而没必要考虑节点的界限(选择在后台完成,对用户是不可见的)。在常规的 DOM 操做不能更有效地修改文档时,使用范围每每能够达到目的。

第 13 章 事件

13.1.3 DOM 事件流

“DOM2 级事件” 规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。

13.2.2 DOM0 级事件处理程序

使用 DOM0 级方法指定的事件处理程序被认为是元素的方法。所以,这时候的事件处理程序是在
元素的做用域中运行;换句话说,程序中的 this 引用当前元素。来看一个例子。

<button id="myBtn">myBtn</button>
<script>
var btn = document.getElementById("myBtn");
btn.onclick = function(){
    alert(this.id); //"myBtn"
};
</script>

将事件处理程序属性的值设置为 null 能够删除经过 DOM0 级方法指定的事件处理程序:
btn.onclick = null;

13.2.3 DOM2 级事件处理程序

“DOM2 级事件” 定义了两个方法,用于处理指定和删除事件处理程序的操做: addEventListener() 和 removeEventListener()。全部 DOM 节点中都包含这两个方法,而且它们都接受 3 个参数:要处理的事件名、做为事件处理程序的函数和一个布尔值。最后这个布尔值参数若是是 true,表示在捕获阶段调用事件处理程序;若是是 false,表示在冒泡阶段调用事件处理程序。

<button id="myBtn">myBtn</button>
<script>
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
    alert(this.id);
}, false);
btn.addEventListener("click", function(){
    alert("Hello world!");
}, false);
</script>

eg:删除事件时必须传入绑定的事件的 “指针”

13.2.4 IE 事件处理程序

IE 实现了与 DOM 中相似的两个方法: attachEvent() 和 detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。因为 IE8 及更早版本只支持事件冒泡,因此经过 attachEvent() 添加的事件处理程序都会被添加到冒泡阶段。

13.3 事件对象

兼容 DOM 的浏览器会将一个 event 对象传入到事件处理程序中。不管指定事件处理程序时使用什么方法(DOM0 级或 DOM2 级),都会传入 event 对象。

<button id="myBtn">myBtn</button>
<script>
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
  alert(event.type); //"click"
};
btn.addEventListener("click", function(event){
  alert(event.type); //"click"
}, false);
</script>

13.4.3 鼠标与滚轮事件

iOS 和 Android 设备的实现很是特别,由于这些设备没有鼠标。在面向 iPhone 和 iPod 中的 Safari 开发时,要记住如下几点。

  • 不支持 dblclick 事件。双击浏览器窗口会放大画面,并且没有办法改变该行为。
  • 轻击可单击元素会触发 mousemove 事件。若是此操做会致使内容变化,将再也不有其余事件发生;若是屏幕没有所以变化,那么会依次发生 mousedown、 mouseup 和 click 事件。轻击不可单击的元素不会触发任何事件。可单击的元素是指那些单击可产生默认操做的元素(如连接),或者那些已经被指定了 onclick 事件处理程序的元素。
  • mousemove 事件也会触发 mouseover 和 mouseout 事件。
  • 两个手指放在屏幕上且页面随手指移动而滚动时会触发 mousewheel 和 scroll 事件。

13.4.7 HTML5 事件

  • DOMContentLoaded 事件 window 的 load 事件会在页面中的一切都加载完毕时触发,但这个过程可能会由于要加载的外部资源过多而颇费周折。而 DOMContentLoaded 事件则在造成完整的 DOM 树以后就会触发,不理会图像、 JavaScript 文件、 CSS 文件或其余资源是否已经下载完毕。与 load 事件不一样,DOMContentLoaded 支持在页面下载的早期添加事件处理程序,这也就意味着用户可以尽早地与页面进行交互。

13.5 内存和性能

  • 事件委托 对 “事件处理程序过多” 问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就能够管理某一类型的全部事件。例如, click 事件会一直冒泡到 document 层次。也就是说,咱们能够为整个页面指定一个 onclick 事件处理程序,而没必要给每一个可单击的元素分别添加事件处理程序。

第 14 章 表单脚本

在 HTML 中,表单是由

元素来表示的,而在 JavaScript 中,表单对应的则是 HTMLFormElement 类型。 HTMLFormElement 继承了 HTMLElement,于是与其余 HTML 元素具备相同的默认属性。不过, HTMLFormElement 也有它本身下列独有的属性和方法。

  • acceptCharset:服务器可以处理的字符集;等价于 HTML 中的 accept-charset 特性。
  • action:接受请求的 URL;等价于 HTML 中的 action 特性。
  • elements:表单中全部控件的集合(HTMLCollection)。
  • enctype:请求的编码类型;等价于 HTML 中的 enctype 特性。
  • length:表单中控件的数量。
  • method:要发送的 HTTP 请求类型,一般是 "get" 或 "post";等价于 HTML 的 method 特性。
  • name:表单的名称;等价于 HTML 的 name 特性。
  • reset():将全部表单域重置为默认值。
  • submit():提交表单。
  • target:用于发送请求和接收响应的窗口名称;等价于 HTML 的 target 特性。

14.5.4 表单与富文本

因为富文本编辑是使用 iframe 而非表单控件实现的,所以从技术上说,富文本编辑器并不属于表单。换句话说,富文本编辑器中的 HTML 不会被自动提交给服务器,而须要咱们手工来提取并提交 HTML。为此,一般能够添加一个隐藏的表单字段,让它的值等于从 iframe 中提取出的 HTML。具体来讲,就是在提交表单以前,从 iframe 中提取出 HTML,并将其插入到隐藏的字段中。

第 15 章 使用 Canvas 绘图

15.2.5 变换

若是你知道未来还要返回某组属性与变换的组合,能够调用 save() 方法。调用这个方法后,当时的全部设置都会进入一个栈结构,得以妥善保管。而后能够对上下文进行其余修改。等想要回到以前保存的设置时,能够调用 restore() 方法,在保存设置的栈结构中向前返回一级,恢复以前的状态。连续调用 save() 能够把更多设置保存到栈结构中,以后再连续调用 restore() 则能够一级一级返回。

<canvas id="drawing" width=" 200" height="200">A drawing of something.</canvas>
<script>
var drawing = document.getElementById("drawing");
//肯定浏览器支持<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");
    context.fillStyle = "#ff0000";
    context.save(); //save1
    context.fillStyle = "#00ff00";
    context.translate(100, 100);
    context.save(); //save2
    context.fillStyle = "#0000ff";
    context.fillRect(0, 0, 100, 200); //从点(100,100)开始绘制蓝色矩形
    context.restore(); //返回save2
    context.fillRect(10, 10, 100, 200); //从点(110,110)开始绘制绿色矩形
    context.restore(); //返回save2
    context.fillRect(0, 0, 50, 50); //从点(0,0)开始绘制红色矩形
}
</script>

15.3 WebGL

书上的太难理解了!

https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API

第 16 章 HTML5 脚本编程

16.1 跨文档消息传递

跨文档消息传送(cross-document messaging),有时候简称为 XDM,指的是在来自不一样域的页面间传递消息。例如, www.wrox.com 域中的页面与位于一个内嵌框架中的 p2p.wrox.com 域中的页面通讯。在 XDM 机制出现以前,要稳妥地实现这种通讯须要花不少工夫。 XDM 把这种机制规范化,让咱们能既稳妥又简单地实现跨文档通讯。

XDM 的核心是 postMessage() 方法。在 HTML5 规范中,除了 XDM 部分以外的其余部分也会提到这个方法名,但都是为了同一个目的:向另外一个地方传递数据。对于 XDM 而言, “另外一个地方” 指的是包含在当前页面中的元素,或者由当前页面弹出的窗口。

16.2 原生拖放

拖动某元素时,将依次触发下列事件:

  1. dragstart
  2. drag
  3. dragend

当某个元素被拖动到一个有效的放置目标上时,下列事件会依次发生:

  1. dragenter
  2. dragover
  3. dragleave 或 drop

第 17 章 错误处理与调试

17.2.1 try-catch 语句

ECMA-262 第 3 版引入了 try-catch 语句,做为 JavaScript 中处理异常的一种标准方式。这与 Java 中的 try-catch 语句是彻底相同的。

try{
    // 可能会致使错误的代码
} catch(error){
    // 在错误发生时怎么处理
}

只要代码中包含 finally 子句,则不管 try 或 catch 语句块中包含什么代码——甚至 return 语句,都不会阻止 finally 子句的执行。来看下面这个函数。

<script>
alert(testFinally());// 0
function testFinally(){
    try {
        return 2;
        alert('try');// 不执行
    } catch (error){
        return 1;
    } finally {
        return 0;
    }
}
</script>

致命错误和非致命错误

非致命错误,能够根据下列一或多个条件来肯定:

  • 不影响用户的主要任务;
  • 只影响页面的一部分;
  • 能够恢复;
  • 重复相同操做能够消除错误。

eg:非致命错误添加 try-catch 可使非致命错误发生后后续代码继续执行,后面的模块继续加载

致命错误,能够经过如下一或多个条件来肯定:

  • 应用程序根本没法继续运行;
  • 错误明显影响到了用户的主要操做;
  • 会致使其余连带错误。

把错误记录到服务器

创建这样一种 JavaScript 错误记录系统,首先须要在服务器上建立一个页面(或者一个服务器入口点),用于处理错误数据。这个页面的做用无非就是从查询字符串中取得数据,而后再将数据写入错误日志中。这个页面可能会使用以下所示的函数:

function logError(sev, msg){
    var img = new Image();
    img.src = "log.php?sev=" + encodeURIComponent(sev) + "&msg=" + encodeURIComponent(msg);
}

这个 logError() 函数接收两个参数:表示严重程度的数值或字符串(视所用系统而异)及错误消息。其中,使用了 Image 对象来发送请求,这样作很是灵活,主要表现以下几方面。

  • 全部浏览器都支持 Image 对象,包括那些不支持 XMLHttpRequest 对象的浏览器。
  • 能够避免跨域限制。一般都是一台服务器要负责处理多台服务器的错误,而这种状况下使用 XMLHttpRequest 是不行的。
  • 在记录错误的过程当中出问题的几率比较低。大多数 Ajax 通讯都是由 JavaScript 库提供的包装函数来处理的,若是库代码自己有问题,而你还在依赖该库记录错误,可想而知,错误消息是不可能获得记录的。

第 18 章 JavaScript 与 XML,第 19 章 E4X

XML 相关

第 20 章 JSON

JSON 的语法能够表示如下三种类型的值。

  • 简单值:使用与 JavaScript 相同的语法,能够在 JSON 中表示字符串、数值、布尔值和 null。但 JSON 不支持 JavaScript 中的特殊值 undefined。
  • 对象:对象做为一种复杂数据类型,表示的是一组无序的键值对儿。而每一个键值对儿中的值能够是简单值,也能够是复杂数据类型的值。
  • 数组:数组也是一种复杂数据类型,表示一组有序的值的列表,能够经过数值索引来访问其中的值。数组的值也能够是任意类型——简单值、对象或数组。

与 JavaScript 的对象字面量相比, JSON 对象有两个地方不同。首先,没有声明变量(JSON 中没有变量的概念)。其次,没有末尾的分号(由于这不是 JavaScript 语句,因此不须要分号)。再说一遍,对象的属性必须加双引号,这在 JSON 中是必需的。属性的值能够是简单值,也能够是复杂类型值。

20.2.2 序列化选项

JSON.stringify() 除了要序列化的 JavaScript 对象外,还能够接收另外两个参数,这两个参数用于指定以不一样的方式序列化 JavaScript 对象。第一个参数是个过滤器,能够是一个数组,也能够是一个函数;第二个参数是一个选项,表示是否在 JSON 字符串中保留缩进。

第 21 章 Ajax 与 Comet

21.1.1 XHR 的用法

  • open():接受 3 个参数:要发送的请求的类型("get"、 "post" 等)、请求的 URL 和表示是否异步发送请求的布尔值。
  • send():接收一个参数,即要做为请求主体发送的数据。若是不须要经过请求主体发送数据,则必须传入 null,由于这个参数对有些浏览器来讲是必需的。
  • readyState:表示请求 / 响应过程的当前活动阶段。
  • onreadystatechange:readyState 属性的值由一个值变成另外一个值,都会触发一次 readystatechange 事件。能够利用这个事件来检测每次状态变化后 readyState 的值。
var xhr = createXHR();
xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.responseText);
        } else {
            alert("Request was unsuccessful: " + xhr.status);
        }
    }
};
xhr.open("get", "example.txt", true);
xhr.send(null);

21.4 跨源资源共享

CORS(Cross-Origin Resource Sharing,跨源资源共享)是 W3C 的一个工做草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。 CORS 背后的基本思想,就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,仍是应该失败。

好比一个简单的使用 GET 或 POST 发送的请求,它没有自定义的头部,而主体内容是 text/plain。在发送该请求时,须要给它附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。下面是 Origin 头部的一个示例:

Origin: http://www.nczonline.net

若是服务器认为这个请求能够接受,就在 Access-Control-Allow-Origin 头部中回发相同的源信息(若是是公共资源,能够回发 "*")。例如:

Access-Control-Allow-Origin: http://www.nczonline.net

若是没有这个头部,或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常状况下,浏览器会处理请求。注意,请求和响应都不包含 cookie 信息。

21.5 其余跨域技术

  • 图像 Ping
var img = new Image();
img.onload = img.onerror = function(){
    alert("Done!");
};
img.src = "http://www.example.com/test?name=Nicholas";
  • JSONP
function handleResponse(response){
    alert("You’ re at IP address " + response.ip + ", which is in " + response.city + ", " + response.region_name);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
  • Comet Ajax 是一种从页面向服务器请求数据的技术,而 Comet 则是一种服务器向页面推送数据的技术。 Comet 可以让信息近乎实时地被推送到页面上,很是适合处理体育比赛的分数和股票报价。

  • SSE 服务器发送事件(Server-Sent Events),是围绕只读 Comet 交互推出的 API 或者模式。 SSE API 用于建立到服务器的单向链接,服务器经过这个链接能够发送任意数量的数据。

  • Web Sockets Web Sockets 的目标是在一个单独的持久链接上提供全双工、双向通讯。

SSE 与 Web Sockets

面对某个具体的用例,在考虑是使用 SSE 仍是使用 Web Sockets 时,能够考虑以下几个因素。

首先,你是否有自由度创建和维护 Web Sockets 服务器?由于 Web Socket 协议不一样于 HTTP,因此现有服务器不能用于 Web Socket 通讯。 SSE 却是经过常规 HTTP 通讯,所以现有服务器就能够知足需求。

第二个要考虑的问题是到底需不须要双向通讯。若是用例只需读取服务器数据(如比赛成绩),那么 SSE 比较容易实现。若是用例必须双向通讯(如聊天室),那么 Web Sockets 显然更好。别忘了,在不能选择 Web Sockets 的状况下,组合 XHR 和 SSE 也是能实现双向通讯的。

第 22 章 高级技巧

22.1.3 惰性载入函数

惰性载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方式

第一种就是在函数被调用时再处理函数。在第一次调用的过程当中,该函数会被覆盖为另一个按合适方式执行的函数,这样任何对原函数的调用都不用再通过执行的分支了。

第二种实现惰性载入的方式是在声明函数时就指定适当的函数。这样,第一次调用函数时就不会损失性能了,而在代码首次加载时会损失一点性能。如下就是按照这一思路重写前面例子的结果

22.1.4 函数绑定

另外一个日益流行的高级技巧叫作函数绑定。函数绑定要建立一个函数,能够在特定的 this 环境中以指定参数调用另外一个函数。该技巧经常和回调函数与事件处理程序一块儿使用,以便在将函数做为变量传递的同时保留代码执行环境。

22.3.2 Yielding Processes

运行在浏览器中的 JavaScript 都被分配了一个肯定数量的资源。不一样于桌面应用每每可以随意控制他们要的内存大小和处理器时间, JavaScript 被严格限制了,以防止恶意的 Web 程序员把用户的计算机搞挂了。其中一个限制是长时间运行脚本的制约,若是代码运行超过特定的时间或者特定语句数量就不让它继续执行。若是代码达到了这个限制,会弹出一个浏览器错误的对话框,告诉用户某个脚本会用过长的时间执行,询问是容许其继续执行仍是中止它。全部 JavaScript 开发人员的目标就是,确保用户永远不会在浏览器中看到这个使人费解的对话框。定时器是绕开此限制的方法之一。

22.3.3 函数节流

浏览器中某些计算和处理要比其余的昂贵不少。例如, DOM 操做比起非 DOM 交互须要更多的内存和 CPU 时间。连续尝试进行过多的 DOM 相关操做可能会致使浏览器挂起,有时候甚至会崩溃。尤为在 IE 中使用 onresize 事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在 onresize 事件处理程序内部若是尝试进行 DOM 操做,其高频率的更改可能会让浏览器崩溃。为了绕开这个问题,你可使用定时器对该函数进行节流。

函数节流背后的基本思想是指,某些代码不能够在没有间断的状况连续重复执行。第一次调用函数,建立一个定时器,在指定的时间间隔以后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另外一个。若是前一个定时器已经执行过了,这个操做就没有任何意义。然而,若是前一个定时器还没有执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求中止了一段时间以后才执行。

22.4 自定义事件

事件是一种叫作观察者的设计模式,这是一种建立松散耦合代码的技术。对象能够发布事件,用来表示在该对象生命周期中某个有趣的时刻到了。而后其余对象能够观察该对象,等待这些有趣的时刻到来并经过运行代码来响应。

观察者模式由两类对象组成: 主体和观察者。主体负责发布事件,同时观察者经过订阅这些事件来观察该主体。该模式的一个关键概念是主体并不知道观察者的任何事情,也就是说它能够独自存在并正常运做即便观察者不存在。从另外一方面来讲,观察者知道主体并能注册事件的回调函数(事件处理程序)。涉及 DOM 上时, DOM 元素即是主体,你的事件处理代码即是观察者。

<script>
function EventTarget(){
  this.handlers = {};
}
EventTarget.prototype = {
  constructor: EventTarget,
  addHandler: function(type, handler){
    if (typeof this.handlers[type] == "undefined"){
      this.handlers[type] = [];
    }
    this.handlers[type].push(handler);
  },
  fire: function(event){
    if (!event.target){
      event.target = this;
    }
    if (this.handlers[event.type] instanceof Array){
      var handlers = this.handlers[event.type];
      for (var i=0, len=handlers.length; i < len; i++){
        handlers[i](event);
      }
    }
  },
  removeHandler: function(type, handler){
    if (this.handlers[type] instanceof Array){
      var handlers = this.handlers[type];
      for (var i=0, len=handlers.length; i < len; i++){
        if (handlers[i] === handler){
          break;
        }
      }
      handlers.splice(i, 1);
    }
  }
};

function handleMessage(event){
  alert("Message received: " + event.message);
}
//建立一个新对象
var target = new EventTarget();
//添加一个事件处理程序
target.addHandler("message", handleMessage);
//触发事件
target.fire({ type: "message", message: "Hello world!"});
//删除事件处理程序
target.removeHandler("message", handleMessage);
//再次,应没有处理程序
target.fire({ type: "message", message: "Hello world!"});
</script>

第 23 章 离线应用与客户端存储

23.3.3 Web 存储机制

  1. Storage 类型 Storage 类型提供最大的存储空间(因浏览器而异)来存储名值对儿。 Storage 的实例与其余对象相似,有以下方法。
  • clear(): 删除全部值; Firefox 中没有实现 。
  • getItem(name):根据指定的名字 name 获取对应的值。
  • key(index):得到 index 位置处的值的名字。
  • removeItem(name):删除由 name 指定的名值对儿。
  • setItem(name, value):为指定的 name 设置一个对应的值。
  1. sessionStorage 对象 sessionStorage 对象存储特定于某个会话的数据,也就是该数据只保持到浏览器关闭。这个对象就像会话 cookie,也会在浏览器关闭后消失。存储在 sessionStorage 中的数据能够跨越页面刷新而存在,同时若是浏览器支持,浏览器崩溃并重启以后依然可用(Firefox 和 WebKit 都支持, IE 则不行)。由于 seesionStorage 对象绑定于某个服务器会话,因此当文件在本地运行的时候是不可用的。存储在 sessionStorage 中的数据只能由最初给对象存储数据的页面访问到,因此对多页面应用有限制。因为 sessionStorage 对象实际上是 Storage 的一个实例,因此可使用 setItem() 或者直接设置新的属性来存储数据。下面是这两种方法的例子。

  2. globalStorage 对象 Firefox 2 中实现了 globalStorage 对象。做为最初的 Web Storage 规范的一部分,这个对象的目的是跨越会话存储数据,但有特定的访问限制。要使用 globalStorage,首先要指定哪些域能够访问该数据。能够经过方括号标记使用属性来实现,如如下例子所示。

  3. localStorage 对象 localStorage 对象在修订过的 HTML 5 规范中做为持久保存客户端数据的方案取代了 globalStorage。与 globalStorage 不一样,不能给 localStorage 指定任何访问规则;规则事先就设定好了。要访问同一个 localStorage 对象,页面必须来自同一个域名(子域名无效),使用同一种协议,在同一个端口上。这至关于 globalStorage[location.host]。

  4. storage 事件 对 Storage 对象进行任何修改,都会在文档上触发 storage 事件。当经过属性或 setItem() 方法保存数据,使用 delete 操做符或 removeItem() 删除数据,或者调用 clear() 方法时,都会发生该事件。这个事件的 event 对象有如下属性。

  • domain:发生变化的存储空间的域名。
  • key:设置或者删除的键名。
  • newValue:若是是设置值,则是新值;若是是删除键,则是 null。
  • oldValue:键被更改以前的值。

第 24 章 最佳实践

24.1.3 松散耦合

  1. 解耦 HTML/JavaScript

一种最多见的耦合类型是 HTML/JavaScript 耦合。在 Web 上, HTML 和 JavaScript 各自表明了解决方案中的不一样层次: HTML 是数据, JavaScript 是行为。由于它们天生就须要交互,因此有多种不一样的方法将这两个技术关联起来。可是,有一些方法会将 HTML 和 JavaScript 过于紧密地耦合在一块儿。

直接写在 HTML 中的 JavaScript,使用包含内联代码的<script > 元素或者是使用 HTML 属性来分配事件处理程序,都是过于紧密的耦合。请看如下代码。

<!-- 使用了 <script> 的紧密耦合的 HTML/JavaScript -->
<script type="text/javascript">
document.write("Hello world!");
</script>

<!-- 使用事件处理程序属性值的紧密耦合的 HTML/JavaScript -->
<input type="button" value="Click Me" onclick="doSomething()" />

通常来讲,你应该避免在 JavaScript 中建立大量 HTML。再一次重申要保持层次的分离,这样能够很容易的肯定错误来源。当使用上面这个例子的时候,有一个页面布局的问题,可能和动态建立的 HTML 没有被正确格式化有关。不过,要定位这个错误可能很是困难,由于你可能通常先看页面的源代码来查找那段烦人的 HTML,可是却没能找到,由于它是动态生成的。对数据或者布局的更改也会要求更改 JavaScript,这也代表了这两个层次过于紧密地耦合了。

HTML 呈现应该尽量与 JavaScript 保持分离。当 JavaScript 用于插入数据时,尽可能不要直接插入标记。通常能够在页面中直接包含并隐藏标记,而后等到整个页面渲染好以后,就能够用 JavaScript 显示该标记,而非生成它。另外一种方法是进行 Ajax 请求并获取更多要显示的 HTML,这个方法可让一样的渲染层(PHP、 JSP、 Ruby 等等)来输出标记,而不是直接嵌在 JavaScript 中。

将 HTML 和 JavaScript 解耦能够在调试过程当中节省时间,更加容易肯定错误的来源,也减轻维护的难度:更改行为只须要在 JavaScript 文件中进行,而更改标记则只要在渲染文件中。

  1. 解耦 HTML/JavaScript

因为 CSS 负责页面的显示,当显示出现任何问题时都应该只是查看 CSS 文件来解决。然而,当使用了 JavaScript 来更改某些样式的时候,好比颜色,就出现了第二个可能已更改和必须检查的地方。结果是 JavaScript 也在某种程度上负责了页面的显示,并与 CSS 紧密耦合了。若是将来须要更改样式表,CSS 和 JavaScript 文件可能都须要修改。这就给开发人员形成了维护上的噩梦。因此在这两个层次之间必须有清晰的划分。

  1. 解耦应用逻辑/事件处理程序

应用和业务逻辑之间松散耦合的几条原则:

  • 勿将 event 对象传给其余方法;只传来自 event 对象中所需的数据;
  • 任何能够在应用层面的动做都应该能够在不执行任何事件处理程序的状况下进行;
  • 任何事件处理程序都应该处理事件,而后将处理转交给应用逻辑。

24.2.1 注意做用域

  1. 避免全局查找
  2. 避免 with 语句

24.2.4 优化 DOM 交互

  1. 最小化现场更新

一旦你须要访问的 DOM 部分是已经显示的页面的一部分,那么你就是在进行一个现场更新。之因此叫现场更新,是由于须要当即(现场)对页面对用户的显示进行更新。每个更改,无论是插入单个字符,仍是移除整个片断,都有一个性能惩罚,由于浏览器要从新计算无数尺寸以进行更新。现场更新进行得越多,代码完成执行所花的时间就越长;完成一个操做所需的现场更新越少,代码就越快。

  1. 使用 innerHTML

有两种在页面上建立 DOM 节点的方法:使用诸如 createElement() 和 appendChild() 之类的 DOM 方法,以及使用 innerHTML。对于小的 DOM 更改而言,两种方法效率都差很少。然而,对于大的 DOM 更改,使用 innerHTML 要比使用标准 DOM 方法建立一样的 DOM 结构快得多。

  1. 使用事件代理

大多数 Web 应用在用户交互上大量用到事件处理程序。页面上的事件处理程序的数量和页面响应用户交互的速度之间有个负相关。为了减轻这种惩罚,最好使用事件代理。

  1. 注意 HTMLCollection

HTMLCollection 对象的陷阱已经在本书中讨论过了,由于它们对于 Web 应用的性能而言是巨大的损害。记住,任什么时候候要访问 HTMLCollection,无论它是一个属性仍是一个方法,都是在文档上进行一个查询,这个查询开销很昂贵。最小化访问 HTMLCollection 的次数能够极大地改进脚本的性能。

24.3.2 验证

JSLint 能够查找 JavaScript 代码中的语法错误以及常见的编码错误。

  • eval() 的使用;
  • 未声明变量的使用;
  • 遗漏的分号;
  • 不恰当的换行;
  • 错误的逗号使用;
  • 语句周围遗漏的括号;
  • switch 分支语句中遗漏的 break;
  • 重复声明的变量;
  • with 的使用;
  • 错误使用的等号(替代了双等号或三等号);
  • 没法到达的代码。

24.3.3 压缩

当谈及 JavaScript 文件压缩,其实在讨论两个东西:代码长度和配重(Wire weight)。代码长度指的是浏览器所需解析的字节数,配重指的是实际从服务器传送到浏览器的字节数。在 Web 开发的早期,这两个数字几乎是同样的,由于从服务器端到客户端原封不动地传递了源文件。而在今天的 Web 上,这二者不多相等,实际上也不该相等。

  1. 文件压缩

由于 JavaScript 并不是编译为字节码,而是按照源代码传送的,代码文件一般包含浏览器执行所不须要的额外的信息和格式。注释,额外的空白,以及长长的变量名和函数名虽然提升了可读性,但倒是传送给浏览器时没必要要的字节。不过,咱们可使用压缩工具减小文件的大小。

给 httpd.conf 文件或者是. htaccess 文件添加如下代码启用对 JavaScript 的自动压缩:

#告诉 mod_zip 要包含任何以.js 结尾的文件
mod_gzip_item_include file \.js$

或者:

#告诉 mod_deflate 要包含全部的 JavaScript 文件
AddOutputFilterByType DEFLATE application/x-javascript
  1. HTTP 压缩

配重指的是实际从服务器传送到浏览器的字节数。由于如今的服务器和浏览器都有压缩功能,这个字节数不必定和代码长度同样。全部的五大 Web 浏览器(IE、 Firefox、 Safari、 Chrome 和 Opera)都支持对所接收的资源进行客户端解压缩。这样服务器端就可使用服务器端相关功能来压缩 JavaScript 文件。一个指定了文件使用了给定格式进行了压缩的 HTTP 头包含在了服务器响应中。接着浏览器会查看该 HTTP 头肯定文件是否已被压缩,而后使用合适的格式进行解压缩。结果是和原来的代码量相比在网络中传递的字节数量大大减小了。

第 25 章 新兴的 API

25.2 Page Visibility API

不知道用户是否是正在与页面交互,这是困扰广大 Web 开发人员的一个主要问题。若是页面最小化了或者隐藏在了其余标签页后面,那么有些功能是能够停下来的,好比轮询服务器或者某些动画效果。而 Page Visibility API(页面可见性 API)就是为了让开发人员知道页面是否对用户可见而推出的。

25.3 Geolocation API

地理定位(geolocation)是最使人兴奋,并且获得了普遍支持的一个新 API。 经过这套 API, JavaScript 代码可以访问到用户的当前位置信息。固然,访问以前必须获得用户的明确许可,即赞成在页面中共享其位置信息。若是页面尝试访问地理定位信息,浏览器就会显示一个对话框,请求用户许可共享其位置信息。

25.4 File API

不能直接访问用户计算机中的文件,一直都是 Web 应用开发中的一大障碍。 2000 年之前,处理文件的惟一方式就是在表单中加入字段,仅此而已。 File API(文件 API)的宗旨是为 Web 开发人员提供一种安全的方式,以便在客户端访问用户计算机中的文件,并更好地对这些文件执行操做。支持 File API 的浏览器有 IE10+、 Firefox 4+、 Safari 5.0.5+、 Opera 11.1 + 和 Chrome。

FileReader 类型实现的是一种异步文件读取机制。能够把 FileReader 想象成 XMLHttpRequest,区别只是它读取的是文件系统,而不是远程服务器。为了读取文件中的数据, FileReader 提供了以下几个方法。

对象 URL 也被称为 blob URL,指的是引用保存在 File 或 Blob 中数据的 URL。使用对象 URL 的好处是能够没必要把文件内容读取到 JavaScript 中而直接使用文件内容。为此,只要在须要文件内容的地方提供对象 URL 便可。要建立对象 URL,可使用 window.URL.createObjectURL() 方法,并传入 File 或 Blob 对象。

25.6 Web Workers

随着 Web 应用复杂性的与日俱增,愈来愈复杂的计算在所不免。长时间运行的 JavaScript 进程会致使浏览器冻结用户界面,让人感受屏幕 “冻结” 了。 Web Workers 规范经过让 JavaScript 在后台运行解决了这个问题。浏览器实现 Web Workers 规范的方式有不少种,可使用线程、后台进程或者运行在其余处理器核心上的进程,等等。具体的实现细节其实没有那么重要,重要的是开发人员如今能够放心地运行 JavaScript,而没必要担忧会影响用户体验了。

JavaScript DOM 编程艺术 第 2 版

第 5 五章 最佳实践

  1. 平稳退化:如今基本全部带交互的网站都使用 Ajax,SAP 也火起来了,平稳退化真是很难实现了(看到第七章发现我以前的观点是错了)
  2. 分离 JS
  3. 向下兼容
  4. 性能考虑

第 6 章 案例研究:图片库改进版

  1. 键盘访问(提升可访问性) onclick 已经帮咱们处理了,eg:下面这个绑定了 onclick 的按钮鼠标左键点击和 tab 而后回车同样弹出 "clicked"
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <button onclick="alert('clecked')">"click" me</button>
</body>
</html>
  1. DOM core 和 HTML-DOM 因为 HTML 与 XML 的类似性及差别,JavaScript 不只实现了标准的 DOM 方法和属性(即由 W3C 制定的),并且还实现了 HTML 特有的 DOM 方法和属性。 DOM Core:标准的 DOM 方法和属性 HTML-DOM:HTML 特有的 DOM 方法和属性

第 7 章 动态建立标记

若元素存在只是为了让 DOM 方法处理他们,那么用 DOM 方法来建立他们才是最合适的选择

== 渐进加强与 Ajax==

一开始以 Ajax 为起点设计网站很难作到平稳退化,但一开始用老式的页面刷新机制设计网站,在此基础上用拦截请求用 Ajax 技术处理就能够实现平稳退化。(渐进加强:HTML 所有完成 ->CSS 所有完成 ->JS 所有完成 -> 网站完成)

== 这样得后端也得作一套页面展现(点开连接和平稳退化用),前端不该再页面加载时使 Ajax(应该由后端生成)==

第 8 章 充实文档的内容

不该使用 DOM 技术将重要内容添加到网页上

如今主流的 MVVM 框架全是使用 JS 生成 DOM。。

accesskey:快捷键

不少大网站都没见用,FF 里要 Alt+Shift+c 才能使用下面设置的快捷键

<a href="http://www.w3school.com.cn/css/" accesskey="c">CSS</a>

第 11 章 HTML5

Modernizr:HTML5/CSS3 特性检测库

HTML5 与 CSS3 基础教程(第 8 版)

第 1 章 网页的构造块

文件名和文件夹名

文件名所有使用小写字母,用短横线分隔单词,用 .html 做为扩展名。混合使用大小写字
母会增长访问者输入正确地址以及找到页面的难度 文件夹的名称也应所有用小写字母。关键是保持一致。若是使用小写字母,访问者和建立者就
没必要在大写字母和小写字母之间转换浪费时间了

语意

  1. == 提高可访问性和互操做性 ==(内容对于借
    助辅助技术的残障访问者是可访问的,
    同时对于台式机、手机、平板电脑及
    其余设备上的浏览器都是可访问的)。
  2. 提高搜索引擎优化(SEO)的效果。
  3. 使维护代码和添加样式变得容易。
  4. (一般)使代码更少,页面加载更快。

万维网的发明者 Tim BernersLee 曾说过一句著名的话:“万维网的力量在于其普适性。让包括残障人士在内的每一个人都能访问万维网,是极为重要的一点。”

small

small 元素表示的含义是法律声明等条文细则。默认状况下,它比其余的文字显示得小一些,可是 == 显示小字号并非使用这个元素的理由 == (之前一直当 small 是小号字体 =_=)

第 3 章 基本 HTML 结构

<html lang="language-code">

曾经使用 Bootstrap4 的时候没找到中文翻译,准备本身翻译一下翻译了两页有点感受有点多,就往下翻了翻看看到底有多少工做量,而后看见有 Translations,点进去一看发现你们基本都知道但很容易忘的一项翻译的人给强调出来了:

HTML5 标准的 doctype 头部定义是首要的,不然会致使样式失真(中国码农每每直接抄国外站点将 lang 写成 en 的小细节也要注意以避免贻笑大方)。

注:之前搜过 lang 相关的里面的规则很复杂的(网页头部的声明应该是用 lang="zh" 仍是 lang="zh-cn"? - 知乎),但通常国内的页面如今通常还都是 zh-CN。

Emmet 设置默认生成的 lang 为 zh-CN: 下面代码添加到 Emmet 的 Settings-User

{
  "snippets": {
    "variables": {
      "lang": "zh-CN"
    }
  }
}

h1 ~ h6

  1. 不要使用 h1 ~ h6 标记副标题、标语以及没法成为独立标题的子标题。
  2. 建立分级标题时,要避免跳过某些级别,如从 h3 直接跳到 h5。不过,容许从低级别跳到高级别的标题。
  3. 要依据内容所处的层次关系选择标题级数,而不是根据你但愿文字应该显示的大小。

main

main 元素是 HTML5 新添加的元素。记住,在一个页面里仅使用一次。

SEO

在 HTML 中,应该将附注栏 (aside) 内容放在 main 的内容以后。出于 SEO 和可访问性的目的,最好将重要的内容放在前面。能够经过 CSS 改变它们在浏览器中的显示顺序。

使用 ARIA 改善可访问性

WAI-ARIA(Web Accessibility Initiative’s Accessible Rich Internet Applications,无障碍
网页倡议 – 无障碍的富互联网应用,也简称 ARIA)是一种技术规范,自称 “有桥梁做用的技术” 。

  1. 使用地标角色role="xxx"
  2. 给元素添加 titletitle="xxx"

第 8 章 操做样式表

@import

@import 指令会影响页面的下载速度和呈现速度,在 Internet Explorer 中影响更为明显。

@media

@media 规则只有 screen 和 print(或许还应加上 all)浏览器支持的很好。

第 9 章 定义选择器

伪元素

  • :first-letter:选择元素的第一个字母
  • :first-line:选择元素的第一行

:first-line 的语法为::first-line。:first-letter 的语法为::firstletter。注意,它们用两个冒号代替了单个冒号。这样修改的目的是将伪元素(有四个,包括::first-line、::first-letter、::before 和::after)与伪类(如: first-child、:link、:hover 等)区分开。

将来,::first-line 和::first-letter 这样的双冒号语法是推荐的方式,现代浏览器也支持它们。原始的单冒号语法则被废弃了,但浏览器出于向后兼容的目的,仍然支持它们。不过,IE9 以前的 InternetExplorer 版本均不支持双冒号。所以,你能够选择继续使用单冒号语法,除非你为 IE8 及如下版本设置了单独的 CSS。

第 12 章 构建响应式网站

  1. 建立内容和 HTML
  2. 移动优先方法
  3. 逐步完善布局

视觉区域(viewport)

<meta name="viewport" content="width=device-width, initial-scale=1" />

  1. 视觉区域的宽度会被设成与设备宽度
  2. 页面的默认缩放级别设成了 100%(换成纵向模式也同样)

兼容旧版 IE

使用 Respond.js

第 13 章 使用 Web 字体

@font-face

第 17 章 视频、音频和其余多媒体

HTML5 并无提供任何保护媒体内容的方法。所以,若是你很在乎对媒体文件的保护,那么暂时不要使用 HTML5 原生多媒体。

附录

HTML Reference

CSS Reference

图解 CSS3 核心技术与案例实战

第二章 CSS3 选择器

  1. 基本选择器:全部浏览器均可用
  2. 层次选择器:基本全部浏览器均可用(部分 IE7+)
  3. 伪类选择器:大部分 IE8+9 + 可用 E:target:匹配 id 为 hash 的元素 E:lang(language):匹配 lang 属性的值为 language 的元素
  4. 伪元素:IE6~8 仅支持单冒号,IE9 + 支持伪元素

    伪元素为 DOM 树没有定义的虚拟元素。不一样于其余选择器,它不以元素为最小选择单元,它选择的是元素指定内容。

使用伪元素能够 DOM 的部份内容(并不是整个 DOM)添加样式

  1. 属性选择器:基本全部浏览器均可用(IE7+)

第三章 CSS3 边框

目前:

  • border-color:浏览器支持的不是很好,尽可能别用
  • border-image:IE11 才支持,谨慎使用 使用一张图片切成九宫格(切的顺序:TRBL),用 8 个边上个格为图片生成边框背景
  • border-radius:浏览器支持的不错,IE9 + 可用 参数:none | 水平参数 {1,4} / [垂直参数 {1,4}]?
  • box-shadow:和 border 不一样,box-shadow 不是盒模型的中的属性,不会计算到宽度

PS:图片圆角我测试能够直接使用,但图片内阴影直接设置无效须要将图片设置为背景,或外面套个 div 实现

第四章 CSS3 背景

  • 多背景:IE8 + 支持 多个背景用逗号隔开

单页 Web 应用 JavaScript 从前端到后端

Web 性能权威指南

图解 TCP/IP(第 5 版)

JavaScript 设计模式

相关文章
相关标签/搜索