快速入门

基本语法

alert("helloworld");

赋值语句

var x = 1;

判断

if(2>1){
    x = 1;
}

注释

alert('hello') // 注释
/* 注释 */

数据类型

   Number

123; // 整数123
0.456; // 浮点数0.456
1.2345e3; // 科学计数法表示1.2345x1000,等同于1234.5
-99; // 负数
NaN; // NaN表示Not a Number,当无法计算结果时用NaN表示
Infinity; // Infinity表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,就表示为Infinity

字符串

'abc' "xyz"

布尔值

true false

逻辑运算

&& || !

比较

> == <

由于 JavaScript 设计缺陷,不要使用==比较,始终坚持使用===比较。

NaN === NaN; // false

isNaN(NaN); // true

浮点数比较,其它语言类似,设置阈值

1 / 3 === (1 - 2 / 3); // false

Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true

null 空值

大多数情况下,我们都应该用 null。undefined 仅仅在判断函数参数是否传递的情况下有用。

数组

[1, 2, 3.14, 'str', null, true]
new Array(1, 2, 3); // 不怎么用

对象

var person = {
    name: 'Bob',
    age: 20,
    tags: ['js', 'web', 'mobile'],
    city: 'Beijing',
    hasCar: true,
    zipcode: null
}; // 这不是字典吗

person.name // 'bob'

变量

var a; // 申明了变量a,此时a的值为undefined
var $b = 1; // 申明了变量$b,同时给$b赋值,此时$b的值为1
var s_007 = '007'; // s_007是一个字符串
var Answer = true; // Answer是一个布尔值true
var t = null; // t的值是null

字符串

转义字符

'I\'m \"OK\"!';

ASCII 字符

'\x41'; // 'A'

Unicode

'\u4e2d\u6587'; // '中文'

多行字符串

`这是一个
多行
字符串`;

模板字符串

`你好, ${name}, 你今年${age}岁了!`; // 比py 少了f 多了$

操作字符串

var s = 'Hello, world!';

s.length; // 13

s[12] // '!'
s[13] // undefined

s.toUpperCase(); // 大写
s.toLowerCase(); // 小写

s.indexOf('world') // 指定字符串出现的位置 没有 -1

s.substring(0, 5); // s[0:5] 左闭右开

注意

  1. 字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果

数组

var arr = [1, 2, 3.14, "hello", null, true];

arr.length; // 6

var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr变为[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; // arr变为[1, 2]

var arr = ["A", "B", "C"];
arr[1] = 99;
arr; // arr现在变为['A', 99, 'C']

var arr = [1, 2, 3];
arr[5] = "x";
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']

indexOf

var arr = [10, 20, '30', 'xyz'];
arr.indexOf(10); // 元素10的索引为0

slice

var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];

arr.slice(0, 3); // 从索引0开始,到索引3结束,但不包括索引3: ['A', 'B', 'C']

arr.slice(3); // 从索引3开始到结束: ['D', 'E', 'F', 'G']

aCoppy = arr.slice() // 开始-结束

push

var arr = [1, 2];
arr.push('A', 'B'); // [1, 2, 'A', 'B']

pop

arr.pop() // [1, 2, 'A']

unshift

var arr = [1, 2];
arr.unshift('A', 'B'); // ['A', 'B', 1, 2]

shift

arr.shift(); // ['B', 1, 2]

sort

arr.sort()

reverse

var arr = [1, 2, 3];
arr.reverse() // [3, 2, 1]

splice

var arr = [0, 1, 2, 3, 4, 5, 6];
arr.splice(2, 3, 9, 9, 9); // 索引2开始 删3个元素 添加3个9 [0, 1, 9, 9, 9, 5, 6]

concat

var a = [1, 2, 3];
var b = [4, 5, 6];
a.concat(b); // [1, 2, 3, 4, 5, 6]

join

var arr = ['A', 'B', 'C', 1, 2, 3];
arr.join('-'); // A-B-C-1-2-3

对象

var h = {
    name: 1,
    id: 2,
    'sex': 3
};

h.name;

h['sex'];

h['name'];

动态修改属性

h.name = 'hdh';

delete h.name;

delete h['id'];

判断是否拥有属性

'name' in h; // true
'school' in h; // false
'toString' in h; // true??? 继承自object

判断属性是否自身拥有

h.hasOwnProperty('toString'); // false

条件判断

省流 和 c++一样

JavaScript 把 null、undefined、0、NaN 和空字符串’’视为 false,其他值一概视为 true

循环

for、while 循环和 c++一样

for… in

var o = {
    name: 'Jack',
    age: 20,
    city: 'Beijing'
};
for (var key in o) { // 注意括号
    console.log(key); // 'name', 'age', 'city'
}

Map

var m = new Map();
var s = new Set();

初始化

var m = new Map([['A': 95], ['B': 100], ['C': 99]]);
var m = new Map();
m.set('A': 100);
m.set('B': 99);

方法

m.get('A');   //查找

m.has('A');   // 存在

m.delete('A') // 删除

Set

会自动去重

创建

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

方法

s.add(4); // [1, 2, 3, 4]

s.delete(4); // [1, 2, 3]

iterable

可迭代的,指 array,set,map

for … of

var a = [1, 2, 3];
for (var x of a){
    ......
}
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
console.log(x);
}
for (var x of s) {
// 遍历Set
console.log(x);
}
for (var x of m) {
// 遍历Map
console.log(x[0] + "=" + x[1]);
}

iterable 内置 forEach 方法

// Array
var a = ["A", "B", "C"];
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
console.log(element + ", index = " + index);
});

// A, index = 0
// B, index = 1
// C, index = 2

// Set
var s = new Set(["A", "B", "C"]);
s.forEach(function (element, sameElement, set) {
// 前两个参数相同
console.log(element);
});

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

函数

function abs(x) {
if (x > 0) return x;
else return -x;
}

定义

匿名函数

var abs = function (x) {
if (x > 0) return x;
else return -x;
};

arguments

function foo(x){
console.log(x);
for (var i=0; i<arguments.length; i++){
console.log(arguments[i]);
}
}
foo(10, 20, 30);

10
10 20 30

变为可选参数

// foo(a[, b], c)
// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a, b, c) {
if (arguments.length === 2) {
// 实际拿到的参数是a和b,c为undefined
c = b; // 把b赋给c
b = null; // b变为默认值
}
// ...
}

rest 参数

function foo(a, b, ...rest) {
console.log(a);
console.log(b);
console.log(rest); // Array
}

foo(1, 2, 3, 4, 5);
1;
(2)[(3, 4, 5)];

作用域

  1. 作用域
  2. 镶套
  3. 变量提升
  4. 全局作用域
  5. 命名空间
var MYAPP = {};

// 其他变量:
MYAPP.name = "myapp";
MYAPP.version = 1.0;

// 其他函数:
MYAPP.foo = function () {
return "foo";
};

let 块级作用域

const 常量

解构赋值

var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
var person = {
name: "小明",
age: 20,
gender: "male",
passport: "G-12345678",
school: "No.4 middle school",
};

// 把passport属性赋值给变量id:
let { name, passport: id, single = true } = person;
name; // '小明'
id; // 'G-12345678'
// 注意: passport不是变量,而是为了让变量id获得passport属性:
passport; // Uncaught ReferenceError: passport is not defined

交换

[x, y] = [y, x];

获取 domain+path

var {hostname:domin, pathnamez:path} = location

如果一个函数接收一个对象作为参数,那么,可以使用解构直接把对象的属性绑定到变量中。例如,下面的函数可以快速创建一个 Date 对象:

function buildDate({ year, month, day, hour = 0, minute = 0, second = 0 }) {
return new Date(
year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second
);
}

buildData({ year: 2022, month: 7, day: 24 });
// Sun Jul 24 2022 00:00:00 GMT+0800 (中国标准时间)

方法

var xiaoming = {
name: "小明",
birth: 1990,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
},
};

拆开

function get_age() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xm = {
name: 1,
birth: 2022,
age: get_age,
};

xm.age(); // 0

get_age(); // NaN

this 指针只在 age 方法的函数内指向 xiaoming,在函数内部定义的函数,this 指向 undefined

先保存 this

var that = this

apply 重新控制 this 指向对象

function get_age() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xm = {
name: 1,
birth: 2022,
age: get_age,
};

xm.age(); // 0

get_age.apply(xm, []);
// 第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数

另一个与 apply()类似的方法是 call(),唯一区别是:

apply()把参数打包成 Array 再传入;

call()把参数按顺序传入。

比如调用 Math.max(3, 5, 4),分别用 apply()和 call()实现如下:

Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5

对普通函数调用,我们通常把 this 绑定为 null

装饰器

基于 apply

var count = 0;
var oldParseInt = parseInt; // 保存原函数

window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};

高阶函数

给函数传个函数作为参数

function add(x, y, f) {
    return f(x) + f(y);
}

add(1, 2, Math.abs);

map

function pow(x) {
    return x*x;
}

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]

reduce

var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
    return x + y;
}); // 25

filter

var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
    return x % 2 !== 0;
});
r; // [1, 5, 9, 15]

巧妙去重

var
    r,
    arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
r = arr.filter(function (element, index, self) {
    return self.indexOf(element) === index;
});

sort

var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return -1;
    }
    if (x > y) {
        return 1;
    }
    return 0;
});
console.log(arr); // [1, 2, 10, 20]

Array 数组方法

……未完待续