JavaScript

JavaScript是一门脚本编程语言,它可以在网页上实现复杂的功能,网页展现给你的不再是简单的静态信息,实时的内容更新,交互式的地图,2D/3D 动画,滚动播放的视频,等等。 JavaScript标准称为ECMAScript标准, 最新正式版ES6

第一步

// example
// <p>玩家1:小明</p>
var para = document.querySelect('p');
para.addEventListener('click', updateName);
function updateName() {
    var name = prompt('请输入一个新名字:');
    para.textContent = '玩家1:' + name;
}

// API分为浏览器API,第三方API
浏览器API分为
文档对象模型API(DOM(Document object Model))
地理位置API
画布(Canvas)和WebGL 创建2D和3D图像
HTMLMediaElement和WebTRC等影音类API
第三方API 如Twitter API

// 添加js
// 内部的js 在</body>前插入<script></script>
// 外部的js <head><script src="script.js"></script></head>
// 内联的js <button onclick="fun()">click me</button> function fun(){} 不要这样做

// 变量
如果不用var声明 name='wcg' 表示全局变量 'use strict'; 强制使用var, 不使用会报ReferenceError
var name = 'wcg'; 字符串 10, 数字 true, 布尔 ['a', 'b'] 数组 {name: 'wcg', age: 100} 对象
typeof name; 获取变量类型

js不区分整数 浮点数
NaN 表示Not a Number
Infinity 表示超过js表达的最大值
null 等于python中的None
undefined 表示未定义

全局变量, js默认有一个全局对象window
var name = 'wcg';
name
window.name // name变量绑定到window的一个属性
function foo() {
    alert('foo');
}
foo();
window.foo();

ES6
let 代替 var 声明块级作用域的变量
const PI = 3.14; 定义常量
let [x, y, z] = ['w', 'c', 'g']

// 操作符
=== !==

// 字符串
var name = `这是一个
多行
字符串`; es6标准
字符串拼接
var message = '你好,' + name;
var message = '你好,${name}'; es6

var name = 'wcg';
引号和python一样, 转义用\
字符型转数字 Number(name);
数字转字符串 'num'; 或 num.toString();
name.length;
name[0];
name.indexOf('cg'); 查找子字符串, 找不到返回-1
name.slice(0, 2);  wc js切片第二个是可选
name.slice(1); cg 没有会到末尾
name.substring(); 同slice
name.toLowerCase(); 调用不会修改原字符串, 而是返回一个新的
name.toUpperCase();
name.replace('g', 'c');

// 数组
var name = new Array(1, 2, 3)
var name = ['w', 'c', 'g']
name[0];
name.length;
字符串转数组 var myArray = myData.split(',');
数组转字符串 var myString = myArray.join(''); 或 var myString = myArray.toString();
name.push('g'); 末尾
name.pop();
name.shift('w'); 开头
name.unshift('w');
name.sort();
name.reverse();
name.splice(2, 3, 'google', 'baidu'); 从2开始, 返回删除的3个数
name.concat([1, 2, 3]) 数组连接

// Map ES6
var m = new Map(['wcg', 100], ['abc', 90])
m.set('admin', 80)
m.get('wcg')
m.delete('admin')

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

// iterable ES6
array map set 用for of遍历
for in 和 for of 区别
for ... in循环由于历史遗留问题, 它遍历的实际上是对象的属性名称, 一个Array数组实际上也是一个对象, 它的每个元素的索引被视为一个属性
var a = ['A', 'B', 'C'];
a.name = 'wcg';
for (var x in a) {
    console.log(x); //'0', '1', '2', 'name'
}
name 不应该包含在内, for of 完全修复了这个问题, 只返回本身的元素

a.forEach(function (element, index, array)) {
    //pass
}

// 高阶函数
var arr = [1, 2, 3];
arr.map(Sting); // ['1', '2', '3']

arr.reduce(function (x,y) {
    return x + y;
}); // 6

var r = arr.filter(function (s) {
    return s > 2;
}); // 3

var s = arr.sort();

// 闭包
function sum(arr) {
    var sum = function() {
        return arr.reduce(function (x, y) {
            return x + y;
        });
    }
    return sum;
}

// 箭头函数相当于匿名函数, 且简化了函数定义 ES6
function (x) {
    return x*x;
}
x => x*x

x => {
    if (x > 0) {
        return x * x;
    }
}

(x, y) => x * x + y * y;
() => 3.14 无参数
x => ({foo: x}) 对象

// 生成器
function* fib(max){
    var
        t,
        a=0,
        b=1,
        n=0;
    while (n<max) {
        yield a;
        [a, b] = [b, a+b];
        n ++;
    }
    return;
}

for (var x of fib(10)) {
    console.log(x);
}

try {
    r1 = yield ajax('http1', data1);
    r2 = yield ajax('http2', data2);
    success(r2);
}
catch (err) {
    handle(err);
}

基础要件

// 条件 && 与 || 或 ! 非
if (true) {
    //pass
} else if (true) {
    //pass
} else {
    //pass
}

switch (choice) {
    case 'sunny':
    //pass
    break;
    case 'rainy':
    //pass
    break;

    default:
    //pass;
}

// 三元运算符
var greeting = (isBirthday)?'Happy birthday':'Good morning'

// 循环
for (var i = 0; i < cats.length; i++) {
    //pass
}

break; continue;

while (true) {
    //pass
}

do {
    //pass
} while (true);

// 函数
function draw() {
    //pass
}
draw();

function foo(x) {
    l = arguments.length //获取所有参数
}

ES6
function foo(a, b, ...rest) {
    console.log(rest) //Array[] 额外参数
}

匿名函数, 一般用来处理事件程序, 如点击
myButton.onclick = function() {
    alert('hello');
}

var myfunc = function() {} 可以赋值给变量
myfunc()

btn.onclick = displayMessage; 函数后面的括号叫函数调用运算符, 直接调用的话用displayMessage(), 否则当点击时才调用这个函数

带参数, 需要放在新的匿名函数里面
btn.onclick = function () {
    displayMessage('hello');
}

// 返回
console.log(); return

// 事件
btn.addEventListener('click', displayMessage);
btn.addEventListener('click', function () {
    //pass
});
btn.removeEventListener('click', displayMessage);

事件对象
function func(e) {
    e.target //事件对象上
}

阻止默认行为
e.preventDefault();

事件冒泡
e.stopPropagation();

// 异常
try {
    //pass
} catch (e) {
    //pass
} finally {
    //pass
}

throw new Error(''); 抛出异常

// 回调
setTimeout(test, 1000); //1000毫秒后执行test

// jQuery
简化DOM操作 $

// underscore
提供完善的函数式编程的方法, 比如在object中使用map _
_.map({a:1, b:2, c:3}, (v, k) => k + '=' + v); // ['a=1', 'b=2', 'c=3']
_.map(obj, function (value, key){return;});
_.every([-1, 2, 3], (x) => x > 0); //false
_.some([-1, 2, 3], (x) => x > 0); true
_.max([]) _.min([]);
_.groupBy(socres, function(x) {});
_.shuffle([1, 2, 3, 4]); 随机打乱顺序
_.sample([1, 2, 3], 2); [1,3]
... 其他见文档

对象

// 创建对象, js对象是无序的
js属性名包含特殊字符, 就必须用""括起来, 且不能用点, 用object['middle-school']
'name' in wcg; 判断属性是否存在, 可继承
wcg.hasOwnProperty('name') 判读自身是否拥有
js的对象键必须是字符串

var objectName = {
    member1Name: member1Value, // 属性
    member2Name: function () {}, // 方法
}

this 指当前代码运行时的对象

js没有用于创建class类的声明, 用构建函数来定义
function Person(name) {
    this.name = name;
    this.greeting = function() {
        alert('hello' +  this.name);
    };
}
var person1 = new Person('wcg');

Object() 构造函数
var person2 = new Object(); 空对象
person2.name = 'wcg'; 往里填充

create()方法 基于现有对象创建新的对象实例
var person3 = Object.create(person2);

js是一种基于原型(prototype)的语言, 每一个对象拥有一个原型对象, 对象的属性和方法定义在Object的构造器函数之上的prototype属性上
在传统的OOP中, 定义类, 此后创建对象实例时, 类中的定义的所有属性和方法都被复制到实例中, 但在js中, 而是在对象实例和构造器之间建立一个链接(__proto__属性, 从构造函数的prototype属性派生), 之后通过上溯原型链, 在构造器中找到这些属性和方法, 如果没找到继续上溯, 直到最后没找到, undefined

person3.constructor 返回用户构造此实例对象的构造函数

一般在构造体定义属性 在prototype属性中定义方法
function Test(a, b, c) {
    this.a = a;
}

Test.prototype.x = function () {}

// apply
function getAge() {
    //pass
}
var wcg = {}
getAge.apply(wcg, []); 参数

js通过原型式的继承
function test(a, b, c, d) {
    Test.call(this, a, b, c); //调用Test构造函数, 绑定this变量
    this.d = d;
}
test.prototype = Object.create(Test.protytype); 设置test的原型和构造器
test.prototype.constructor = Test;
test.prototype.greeting = function () {};

最好通过中间函数F实现
function inherits(child, parent) {
    var F = function () {
        F.prototype = parent.prototype;
        child.prototype = new F();
        child.prototype.constructor = child;
    }
}
inherits(test, Test)
test.prototype.greeting = function () {};

// class ES6
function Student(name) {
    this.name = name;
}
Student.prototype.hello = function () {return;}
// class
class Student{
    constructor(name){
        this.name = name;
    }
    hello(){
        return;
    }
}
// class继承
class PrimaryStudent extends Student {
    constructor(name, grade){
        super(name); //super调用父类的构造方法
        this.grade = grade;
    }
    myGrade(){}
}

JSON对象就是基于js的对象

最简单的xmlhttprequest请求, ajax请求是异步的, 要通过回调函数获得响应
var requestURL = 'https://blog.itswcg.com';
var request = new XMLHttpRequest();
request.open('GET', requestURL);
request.responseType = 'json';
request.send();

request.onload = function() {
    var response = reqeust.response; 事件处理, 只有请求成功后才触发load事件
}

ajax 浏览器同源策略 url的域名必须和当前页面完全一致, 域名 协议http 端口要完全一样
h5 CORS 设置header Access-Control-Allow-Origin: *
还要设置Access-Control-Request-Method: GET, POST ...

// Promise 承诺将来会执行 ES6
new Pormise(test).then(function (result) {
    console.log('success');
}).catch(function (reason) {
    console.log('failed')
})

Promise.all([p1, p2]).then() 同时执行p1 p2, 完成后才执行then
Promise.race([p1, p2]).then() p1 p2 执行速度快的then, 慢的执行结果被丢弃

// Canvas h5
<canvas id="test-canvas" width="300" height="200"></canvas>
var canvas = document.getElementById('test-canvas');
var ctx = canvas.getContent('2d'); 2d
var gl = canvas.getElementById('webgl'); 3d

// JSON 转换
var mystr = JSON.stringify(myjson);
var myjson = JSON.parse(mystr);

// 标准对象
typeof 可以判断number, boolean, string, function, undefined
判断Array使用Array.isArray(arr);
判断null myVar === null;
判断全局变量 typeof window.myVar === 'undefined';
判断局部变量 typeof myVar === 'undefined';

数字转字符串
123..toString();
(123).toString();

Date
var now = new Date();
now;
now.getFullYear();
now.getTime();
var d = new Date(2018, 11, 13, 19, 32, 123); js月份是0~11

客户端API

IE10, chrome, safari, firefox 支持ES6

window 是载入浏览器的标签, 不止充当全局作用域, 而且表示浏览器窗口
navigator 表示浏览器存在web上的状态和标识, 如获取摄像头, 地理位置
document 是载入窗口的实际页面

window 操作
window.innerWidth;
window.innerHeight;

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

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

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

// location对象表示当前页面的URL信息
location = 'http://www.example.com:8080/path/index.html?a=1&b=2#TOP'
location.protocol; // 'http'
location.host; // 'www.example.com'
location.port; // '8080'
location.pathname; // '/path/index.html'
location.search; // '?a=1&b=2'
location.hash; // 'TOP'

location.reload(); //重新加载当前页面
location.assign('https://blog.itswcg.com') //加载新的

DOM操作
var link = document.querySelector('#id1'); 返回第一个a
var links = document.querySelectorAll('a'); 返回所有, 数组
document.getElementById('id');
document.getElementByTagName('p');
document.getElementsByClassName('red');
document.cookie; //获取cookie

var cs = link.children;
var first = link.firstElementChild; last

var para = document.querySelector('#id2'); 更新html
p.innerHTML = 'ABC' //设置文本
p.innerHTML = 'ABC <span style="color:red">RED</span>'; //设置html,要避免xss攻击
p.innerText = '<scrip></script>' //html自动编码, 无法设置js节点
p.textContent = '' //返回所有文本

var para = document.createElement('p'); 创建节点
para.textContent = '';
sect.appendChild(para);
sect.removeChild(para);
sect.parentNode.removeChild(sect); 删除自己
sect.insertBefore(para, p); 插入p之前

para.style.color = 'white';  操作css
para.style.backgroundColor = 'black';
para.setAttribute('class', 'highlight');

var input = document.getElementById('email'); 操作表单
input.value; 用户输入的值
mon.checked; true or false 复选框
input.value = 'wcg'; 设定值

网络请求
fetch(url).then(function(response){
    return response.text()
}).then(function(text){
    poemDisplay.textContent = text;
})

cookie 是过时的
现在用web storage和indexedDB api
未来 cache api

localStorage.setItem('name', 'wcg');
var myName = localStorage.getItem('name');
localStorage.removeItem('name');

let db; 块级作用域
window.onload = function() {
    let request = window.indexedDB.open('notes', 1);
    let objectStore = db.createObjectStore('notes', {keyPath:'id', autoIncreament:true});
    objectStore.createIndex('title', 'title', {unique:false});
    objectStore.createIndex('body', 'body', {unique:false});
}