Javascript知识点整合

2018-12-11  本文已影响0人  _源稚生

字符串

单行字符串:

‘字符串’或“字符串”

多行字符串:

`多行
字符串`

字符串操作:


数组

基本属性

1、取得数组长度
arr.length

2、改变数组长度,数组会发生改变
var arr = [1, 2, 3]; arr.length = 6;//arr变为[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;// arr变为[1, 2]

3、数组赋值超过了索引,会引起数组变化,而不会报错
arr[5] = '6'; arr; // arr变为[1, 2, 3, undefined, undefined, '6']

数组操作

var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回删除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只删除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不删除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因为没有删除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']

对象

var xiaoming = {
    name: '小明',
    birth: 1990,
    'mid-school': 'No.1 Middle School',
    height: 1.70,
    weight: 65,
    score: null
};

循环

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

(过滤对象继承属性hasOwnProperty())

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

遍历一个数组

var a = ['A', 'B', 'C'];
for (var i in a) {
    console.log(i); // '0', '1', '2'
    console.log(a[i]); // 'A', 'B', 'C'
}
//遍历得到的对象是String而不是number
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]);
}

注意:相对比for...in,有以下不同

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x in a) {
    console.log(x); // '0', '1', '2', 'name'
}

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x of a) {
    console.log(x); // 'A', 'B', 'C'
}
var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) {
    console.log(element);
});

Map的回调函数参数依次为value、key和map本身:

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

Map和Set

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

var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

函数

function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
}

foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

foo(1);
// 结果:
// a = 1
// b = undefined
// Array []
'use strict';

var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript'

因为js默认有一个全局变量window,所以直接访问course和访问window.course是一样的


所以,如果想定义全局变量,为了避免更window下的变量冲突,最好用以下的方法,将需要定义的变量封装到唯一命名空间中

// 唯一的全局变量MYAPP:
var MYAPP = {};

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

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

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var that = this; // 在方法内部一开始就捕获this
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - that.birth; // 用that而不是this
        }
        return getAgeFromBirth();
    }
};

xiaoming.age(); // 25

this指针只在age方法的函数内指向xiaoming,在函数内部定义的函数,this又指向undefined了,所以要定义一个that变量捕获this

'use strict';

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]

filter可以接收回调函数

var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
    console.log(element); // 依次打印'A', 'B', 'C'
    console.log(index); // 依次打印0, 1, 2
    console.log(self); // self就是变量arr
    return true;
});

例如:去除数组中的重复元素

'use strict';

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

sort
排序函数,可以接收一个函数实现自定义排序,返回的是改变后的当前数组
例如:数组元素从小到大排序

var arr = [10, 20, 1, 2];
arr.sort((x, y) => {return x-y}); // [20, 10, 2, 1]

闭包
一般函数的返回值是一个具体的数据类型,但是闭包是把函数内部定义的一个函数作为结果返回
例如:下面的求和函数,如果不需要立刻得到求和结果,后面需要进一步计算等操作,只需返回求和函数

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

当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数,要获得结果,需要调用函数f(); // 15
注意:
当我们调用lazy_sum()时,每次调用都会返回一个新的函数,f1()f2()的调用结果互不影响。

var f1 = lazy_sum([1, 2, 3, 4, 5]);
var f2 = lazy_sum([1, 2, 3, 4, 5]);
f1 === f2; // false

闭包的作用:
1、闭包可以实现封装私有变量

'use strict';

function create_counter(initial) {
    var x = initial || 0;
    return {
        inc: function () {
            x += 1;
            return x;
        }
    }
}

注意:里面的x是局部变量,并且外部代码根本无法访问,也就是说这个局部变量对外隐藏

2、闭包可以把多参数变为单参数
例如,要计算x的y次幂可以用Math.pow(x, y)函数,不过考虑到经常计算x的二次幂或x三次幂,我们可以利用闭包创建新的函数pow2pow3

'use strict';

function make_pow(n) {
    return function (x) {
        return Math.pow(x, n);
    }
}
// 创建两个新函数:
var pow2 = make_pow(2);
var pow3 = make_pow(3);

console.log(pow2(5)); // 25
console.log(pow3(7)); // 343

箭头函数

//一个参数:
x => x + x

// 两个参数:
(x, y) => x * x + y * y

// 无参数:
() => 3.14

// 可变参数:
(x, y, ...rest) => {
    var i, sum = x + y;
    for (i=0; i<rest.length; i++) {
        sum += rest[i];
    }
    return sum;
}

//返回一个对象,注意括号`()`
x => ({foo: x})

注意:
使用箭头函数修复了this的作用域,也就是说之前的var that = this;在箭头函数里面可以直接省略,因为this始终只想外层调用者obj

generator
因为generator可以在执行过程中多次返回,所以它看上去就像一个可以记住执行状态的函数
例如:要编写一个产生斐波那契数列的函数

function fib(max) {
    var
        t,
        a = 0,
        b = 1,
        arr = [0, 1];
    while (arr.length < max) {
        [a, b] = [b, a + b];
        arr.push(b);
    }
    return arr;
}

// 测试:
fib(5); // [0, 1, 1, 2, 3]
fib(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

用generator改写

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

调用generator对象有两个方法:

1、调用generator对象有两个方法

var f = fib(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: false}
f.next(); // {value: undefined, done: true}

2、用for ... of循环迭代generator对象

'use strict'

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); // 依次输出0, 1, 1, 2, 3, ...
}

标准对象

1、不要使用new Number()、new Boolean()、new String()创建包装对象;

2、用parseInt()或parseFloat()来转换任意类型到number;

3、用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;

4、通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};

5、typeof操作符可以判断出number、boolean、string、function和undefined;

6、判断Array要使用Array.isArray(arr);

7、判断null请使用myVar === null;

8、判断某个全局变量是否存在用typeof window.myVar === 'undefined';

9、函数内部判断某个变量是否存在用typeof myVar === 'undefined'。

注意:number对象调用toString()

123..toString(); // '123', 注意是两个点!
(123).toString(); // '123'
var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳
var re1 = /ABC\-001/;
var re2 = new RegExp('ABC\\-001');

re1; // /ABC\-001/
re2; // /ABC\-001/

判断正则表达式是否匹配

var re = /^\d{3}\-\d{3,8}$/;
re.test('010-12345'); // true
re.test('010-1234x'); // false
re.test('010 12345'); // false

切分字符串

'a b   c'.split(' '); // ['a', 'b', '', '', 'c']
'a b   c'.split(/\s+/); // ['a', 'b', 'c']

分组
()表示的就是要提取的分组(Group)

var re = /^(\d{3})-(\d{3,8})$/;
re.exec('010-12345'); // ['010-12345', '010', '12345']
re.exec('010 12345'); // null

全局匹配
全局匹配可以多次执行exec()方法来搜索一个匹配的字符串

var s = 'JavaScript, VBScript, JScript and ECMAScript';
var re=/[a-zA-Z]+Script/g;

// 使用全局匹配:
re.exec(s); // ['JavaScript']
re.lastIndex; // 10

re.exec(s); // ['VBScript']
re.lastIndex; // 20

re.exec(s); // ['JScript']
re.lastIndex; // 29

re.exec(s); // ['ECMAScript']
re.lastIndex; // 44

re.exec(s); // null,直到结束仍没有匹配到
'use strict';

var xiaoming = {
   name: '小明',
   age: 14,
   gender: true,
   height: 1.65,
   grade: null,
   'middle-school': '\"W3C\" Middle School',
   skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};
var s = JSON.stringify(xiaoming, ['name', 'skills'], '   ');
console.log(s);

三个参数意义如下:
xiaoming是对象
['name', 'skills']是筛选的属性
' '是显示缩进
(注意,第二个参数也可以是函数,用于改变对象的key或者value)

反序列化

JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45
class Student {
    constructor(name) {
        this.name = name;
    }

    hello() {
        alert('Hello, ' + this.name + '!');
    }
}

var xiaoming = new Student('小明');
xiaoming.hello();

继承

class PrimaryStudent extends Student {
    constructor(name, grade) {
        super(name); // 记得用super调用父类的构造方法!
        this.grade = grade;
    }

    myGrade() {
        alert('I am at grade ' + this.grade);
    }
}

(内容参考廖雪峰官网,部分代码引用这里

上一篇下一篇

猜你喜欢

热点阅读