廖JS课程

2015-08-06  本文已影响0人  6ebb5d08123d

1. 字符串


'\x41' // 等同于A
'\u4e2d\u6587' // 等同于'中文'
alert(`多行
字符串
测试`);

2. 数组


3. 对象


4. Map和Set


JavaScript的默认对象表示方式{}可以视为其他语言中的MapDictionary的数据结构,即一组键值对。
 但是JavaScript的对象有个小问题,就是键必须是字符串。但实际上Number或者其他数据类型作为键也是非常合理的
 为了解决这个问题,最新的ES6规范引入了新的数据类型Map

4.1 Map

Map是一组键值对的结构,具有极快的查找速度。
 举个例子,假设要根据同学的名字查找对应的成绩,如果用Array实现,需要两个Array

var names = ['Michael', 'Bob', 'Tracy'];
var scores = [95, 75, 85];

给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,Array越长,耗时越长。
 如果用Map实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用JavaScript写一个Map如下:

var m = new Map([['Michael', 95], ['Bob', 75], 
        ['Tracy', 85]]);
m.get('Michael'); // 95

通过上面的例子,可以看出Map其实看成一个二维数组,Map中的每一个元素都是一个一维数组,有一个key 和 与之对应的一个value

4.2 Set

SetMap类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key
 要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set

var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3

重复元素在Set中自动被过滤

var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}

通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果

>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}

通过delete(key)方法可以删除元素:

var s = new Set([1, 2, 3]);
s; // Set {1, 2, 3}
s.delete(3);
s; // Set {1, 2}

5. iterable


遍历Array可以采用下标循环,遍历MapSet就无法使用下标
 为了统一集合类型,ES6标准引入了新的iterable类型,ArrayMapSet都属于iterable类型
 具有iterable类型的集合可以通过新的for ... of循环来遍历for ... of循环是ES6引入的新的语法。

var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array 
  alert(x);
}
for (var x of s) { // 遍历Set 
  alert(x);
}
for (var x of m) { // 遍历Map 
  alert(x[0] + '=' + x[1]);
}
 var a = ['A', 'B', 'C'];
    a.forEach(function (element, index, array) { 
         // element: 指向当前元素的值 
         // index: 指向当前索引 
         // array: 指向Array对象本身
         alert(element);
 });

2. SetArray类似,但Set没有索引,因此回调函数最多两个参数

    var s = new Set(['A', 'B', 'C']);
    s.forEach(function (element, set) {
       console.log(element); // 'A','B','C'
    });

3. Map的回调函数参数依次为valuekeymap本身

    var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
    m.forEach(function (value, key, map) {
        console.log(value); // 'x','y','z'
    });

6. 函数


6.1 函数的定义与调用

function foo() {
    return
        { name: 'foo' };
}
console.log(foo()); // undefined
---> 相当于下面:
function foo() {
    return; // 自动添加了分号,相当于return undefined;
        { name: 'foo' }; // 这行语句已经没法执行到了
}

所以正确的多行写法是:

function foo() {
    return { // 这里不会自动加分号,因为{表示语句尚未结束
        name: 'foo'
    };
}

6.2 变量的作用域

'use strict';
function foo() {
    var x = 'Hello, ' + y; // 'Hello, undefined'
    alert(x);
    var y = 'Bob';
}
foo();
// 唯一的全局变量MYAPP:
var MYAPP = {};
// 其他变量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;
// 其他函数:
MYAPP.foo = function () {
    return 'foo';
};

把自己的代码全部放入唯一的名字空间MYAPP中,会大大减少全局变量冲突的可能。
 许多著名的JavaScript库都是这么干的:jQueryYUIunderscore等等。

使用`let`声明一个块级作用域
'use strict';
 const PI = 3.14;
 PI = 3; // 某些浏览器不报错,但是无效果!
 PI; // 3.14

6.3 generator

generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次
 先看一个generator的栗子:

`generator`的小栗子
 再举个栗子,fibnacci数列:
`generator`对象中的 `next( )`方法介绍
 直接调用一个generator和调用函数不一样,fib(5)仅仅是创建了一个generator对象,还没有去执行它
 调用generator对象有两个方法,一是不断地调用generator对象的next()方法,如上面的栗子所示。 **为了保证异步事件的执行顺序,需要嵌套,十分丑陋**

像上面的例子中,回调越多,为了保证代码的执行顺序,代码嵌套的层级越多,代码越难看
  有了generator的美好时代,用AJAX时可以这么写:

使用`generator`展开异步事件
  看上去是同步的代码,实际执行是异步的

7. 标准对象


7.1 Date

7.2 正则表达式

8. 面向对象编程


8.1 原型继承

在传统的基于Class的语言如Java、C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass
 由于这类语言严格区分类和实例,继承实际上是类型的扩展。但是JavaScript由于采用原型继承,我们无法直接扩展一个Class,因为根本不存在Class这种类型
 比较新颖的继承方法的实现:

原型继承

9. 浏览器


由于JavaScript的出现就是为了能在浏览器中运行,所以,浏览器自然JavaScript开发者必须要关注的。
 目前主流的浏览器分这么几种:

navigator.appName:浏览器名称;
navigator.appVersion:浏览器版本;
navigator.language:浏览器设置的语言;
navigator.platform:操作系统类型;
navigator.userAgent:浏览器设定的User-Agent字符串。

请注意navigator的信息可以很容易地被用户修改,所以JavaScript读取的值不一定是正确的,尽量不要使用navigator.userAgent提供的用户代理字符串去判断客户端浏览器。
 正确的方法是充分利用JavaScript对不存在属性返回undefined的特性,直接用短路运算符||计算

var width = window.innerWidth || document.body.clientWidth;

screen.width:屏幕宽度,以像素为单位;
screen.height:屏幕高度,以像素为单位;
screen.colorDepth:返回颜色位数,如8、16、24;

10. DOM操作


positionString:
beforeBegin afterBegin beforeEnd afterEnd

11. 表单操作

12. 操作文件


在HTML表单中,可以上传文件的唯一控件就是<input type="file">
 尤其需要注意:

当一个表单包含<input type="file">时,表单的enctype必须指定为multipart/form-datamethod必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据

出于安全考虑,浏览器只允许用户点击<input type="file">来选择本地文件,用JavaScript对<input type="file">value赋值是没有任何效果的。当用户选择了上传某个文件后,JavaScript也无法获得该文件的真实路径

JS无法获取上传文件的真实路径
 通常,上传的文件都由后台服务器处理,JavaScript可以在提交表单时对文件扩展名做检查,以便防止用户上传无效格式的文件

13. Ajax


refreshPrice({"0000001":{"code": "0000001", ... });

因此我们需要首先在页面中准备好回调函数:

function refreshPrice(data) {
    var p = document.getElementById('test-jsonp');
    p.innerHTML = '当前价格:' +
        data['0000001'].name +': ' + 
        data['0000001'].price + ';' +
        data['1399001'].name + ': ' +
        data['1399001'].price;
  }

最后用getPrice( )函数触发,就完成了跨域加载数据:

动态加入`<script>`元素
 4. CORS
 如果浏览器支持HTML5,那么就可以一劳永逸地使用新的跨域策略:CORS
 CORS全称Cross-Origin Resource Sharing,是HTML5规范定义的如何跨域访问资源
 了解CORS前,我们先搞明白概念:
 Origin表示本域,也就是浏览器当前页面的域。当JavaScript向外域(如sina.com)发起请求后,浏览器收到响应后,首先检查Access-Control-Allow-Origin是否包含本域,如果是,则此次跨域请求成功,如果不是,则请求失败,JavaScript将无法获取到响应的任何数据。
 可见,跨域能否成功,取决于对方服务器是否愿意给你设置一个正确Access-Control-Allow-Origin,决定权始终在对方手中
 上面这种跨域请求,称之为“简单请求”。简单请求包括GETHEADPOSTPOSTContent-Type类型仅限application/x-www-form-urlencodedmultipart/form-datatext/plain),并且不能出现任何自定义头(例如,X-Custom: 12345),通常能满足90%的需求。
 在引用外域资源时,除了JavaScript和CSS外,都要验证CORS。例如,当你引用了某个第三方CDN上的字体文件时:
使用@font-face引用 `第三方CDN`上的字体
 对于PUTDELETE以及其他类型如application/jsonPOST请求,在发送AJAX请求之前,浏览器会先发送一个OPTIONS请求(称为preflighted请求)到这个URL上,询问目标服务器是否接受:
OPTIONS /path/to/resource HTTP/1.1
Host: bar.com
Origin: http://bar.com
Access-Control-Request-Method: POST

服务器必须响应并明确指出允许的Method:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.com
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
Access-Control-Max-Age: 86400

浏览器确认服务器响应的Access-Control-Allow-Methods头确实包含将要发送的AJAX请求的Method,才会继续发送AJAX,否则,抛出一个错误。
 由于以POSTPUT方式传送JSON格式的数据在REST中很常见,所以要跨域正确处理POSTPUT请求,服务器端必须正确响应OPTIONS请求
 浏览器对CORS的实现情况:

  • IE8中引入了XDR类型
    XDR与XHR有一些不同之处:
    cookie不会随请求发送,也不会随响应返回;
    只能设置请求头部信息中的Content-Type字段;
    不能访问响应头部信息;
    只支持GET和POST方法;
     所有的XDR请求都是异步执行的,请求返回后,会触发load事件,但只能访问响应的原始文本(responseText),不能访问status,并且,只要响应有效就会触发load事件。如果失败(包括响应中缺少Access-Control-Allow-Origin头部)就会触发error事件
     为了支持POST请求,XDR对象提供了contentType属性,用来表示发送数据的格式。
  • 其他浏览器对CORS的支持
     其他支持HTML5的浏览器,都通过XHR对象实现对CORS的原生支持。要请求位于另一个域中的资源,使用标准的XHR对象并在open( )方法中传入绝对URL即可
     跨域的XHR对象可以访问status属性,而且还支持同步请求。不过,跨域XHR对象也会有一些限制
    不同使用setRequestHeader( )设置自定义头部;
    不能发送和接收cookie;
    调用getAllResponseHeader( )方法总会返回空字符串;
    注意以下内容,XDR和跨域XHR有如下共同属性/方法:
    abort( ):用于停止正在进行的请求
    onerror:用于替代onreadystatechange检测错误
    onload:用于替代onreadystatechange检测成功
    responseText:用于取得响应内容
    send( ):用于发送请求

跨浏览器的CORS

跨浏览器的`CORS`实现

14. promise


在JavaScript的世界中,所有代码都是单线程执行的。
 由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步操作会在将来的某个时间点触发一个函数调用,AJAX就是典型的异步操作。

使用promise可以实现ajax的链式操作
 这种链式写法的好处在于,先统一执行AJAX逻辑,不关心如何处理结果,然后,根据结果是成功还是失败,在将来的某个时候调success函数或fail函数
 古人云:“君子一诺千金”,这种“承诺将来会执行”的对象在JavaScript中称为Promise对象
 Promise有各种开源实现,在ES6中被统一规范,由浏览器直接支持
上一篇下一篇

猜你喜欢

热点阅读