Javascript知识点整合
字符串
单行字符串:
‘字符串’或“字符串”
多行字符串:
`多行
字符串`
字符串操作:
-
字符串连接
‘+’号 -
长度
String.length -
指定位置
var s = ‘STRING’; s[0] === 'S';
(注意:字符串是不可变的,若赋值s[0] = 'T',s仍为‘STRING’) -
字符串变为大写
toUpperCase() -
字符串全部变为小写
toLowerCase() -
搜索指定字符串出现的位置
indexOf(),例:s.indexOf('ING');//返回3
-
返回指定索引区间的字串
substring(),例:s.substring(0, 3);//返回'STR'
数组
基本属性
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']
数组操作
-
搜索指定的元素位置
indexOf() -
截取一段数组元素,对比substring()
slice() -
向末尾添加若干元素
push() 例:arr.push('4', '5'); arr; // arr变为[1, 2, 3, '4', '5']
-
向末尾删除一个元素
pop() 例:arr.pop(); arr; // arr变为[1, 2]
-
向头部添加若干元素
unshift() 例:arr.unshift('4', '5'); arr; // arr变为['4', '5', 1, 2, 3]
-
在头部删除第一个元素
shift() 例:arr.shift(); arr; // arr变为[2, 3]
-
按照默认方式排序
sort() -
把数组所有元素反转
reverse() -
在数组指定位置删除若干元素,在同样的位置添加元素
splice() 例:
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']
-
两个数组合并,返回一个新的数组
concat() 例:
var arr = ['A', 'B', 'C'];
var added = arr.concat([1, 2, 3]);
added; // ['A', 'B', 'C', 1, 2, 3]
-
将数组的每一个元素用指定的字符串连接
join() 例:var arr = [1, 2, 3]; arr.join('-'); // '1-2-3'
对象
var xiaoming = {
name: '小明',
birth: 1990,
'mid-school': 'No.1 Middle School',
height: 1.70,
weight: 65,
score: null
};
-
对象属性操作
xiaoming.name;//小明
xiaohong['middle-school']; // 'No.1 Middle School'
xiaohong['name']; // '小红'
-
新增属性
xiaoming.age = 18; // 新增一个age属性
-
删除属性
delete xiaoming.age; // 删除age属性
-
判断是否拥有某一属性
'name' in xiaoming; // true
'grade' in xiaoming; // false
注意:
in判断的是该属性是否存在,同时也包括该属性继承的object对象所有属性,例如toString
'toString' in xiaoming; // true
如果判断自身拥有的,用hasOwnProperty()方法:
xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false
循环
- for ... in
遍历一个对象
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
-
while
-
do while
-
for ... of
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'
}
- forEach
可用于遍历map和set
因为set类似于数组,所有它只有key没有value
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
- Map
类似于其他编程语言的字典
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
- Set
存储key不存储value
函数
- rest参数
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 []
-
变量提升
把所有要声明的对象提到函数顶部 -
js引擎自动在末尾添加分号机制
-
全局作用域
不在任何函数内定义的变量就具有全局作用域
'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';
};
- this
'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
- 高阶函数
一个函数就可以接收另一个函数作为参数
Map
作用于数组,可以通过接受函数来改变数组中每一个元素的值
'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三次幂,我们可以利用闭包创建新的函数pow2
和pow3
'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'
- Date
获取当前时间,注意月份,0代表一月
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形式表示的时间戳
- RegExp
正则表达式匹配字符串
有两种方法创建RexExp对象:
第一种方式是直接通过/正则表达式/
写出来,第二种方式是通过new RegExp('正则表达式')
创建一个RegExp对象
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,直到结束仍没有匹配到
- JSON
序列化
'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
- 面向对象编程
创建一个Student对象
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);
}
}