希望对找与
javascript
相关工作的同学有所帮助,敲得好累~
P1 基本概念
1.1 标识符
1.2 关键字和保留字
1.3 变量
var a = 'hello'; // var声明a变量,并初始化为 'hello'
var b; // var声明b变量,但未初始化
console.log(b); // undefined
console.log(c); // c没有声明
// Uncaught ReferenceError: c is not defined
在严格模式下,给未声明的变量赋值会抛出 ReferenceError
1.4 数据类型
5种基本数据类型:undefined
, null
, boolean
, number
, string
复杂数据类型:Object
1.5 typeof 操作符
可能返回字符串结果:undefined
, boolean
, string
, number
, object
, function
console.log(typeof 9); // number
console.log(typeof true); // boolean
console.log(typeof 'asd'); // string
console.log(typeof null); // object
console.log(typeof [1,2,3]); // object
console.log(typeof /\d+/); // object
console.log(typeof Array.prototype.forEach); // function
1.6 null 类型
null
表示一个空对象指针。
如果定义的变量是用来保存对象的,最好将它初始化为 null
。这样一来,只要直接检查变量是否为null
来判断它是否已经保存了一个对象的引用。
if (car !== null) {
// 对car对象执行某些操作
}
与undefined
的比较
console.log(null == undefined) // true
console.log(null === undefined) // false
1.7 Boolean 类型
var a = new Boolean(123); // 这是个对象
var a = Boolean(123);
console.log(typeof a) // object
console.log(a == true) // true
console.log(typeof b) // boolean
console.log(b == true) // true
数据类型 | true | false |
---|---|---|
Boolean | true | false |
String | 非空字符串 | "" |
Number | 非零数字(包括无穷大) | 0或NAN |
Object | 任何对象 | null |
Undefined | 不存在的 | undefined |
1.8 Number 类型
- 默认是十进制整数
- 八进制:以
0
开头,然后是0-7
(严格模式无效,抛出错误) - 十六进制:以
0x
开头,然后是0-9及A-F,a-f
var a = 55 //55
a = 070 // 八进制的56
a = 079 //无效的八进制,解析为79
a = 0xA // 十六进制的10
a = 0x1f // 十六进制的31
浮点数值的最高精度是17位小时,但算术计算时的精确度远不如整数。例如 0.1+0.2
的结果不是 0.3
,而是 0.30000000000000004
// 求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题
// 输入 multiply(3, 0.0001)
// 输出 0.0003
function multiply(a, b) {
//求两个数中精度大的一个
var stra = a.toString();
var strb = b.toString();
var len = Math.max(stra.length-stra.indexOf('.')-1,strb.length-strb.indexOf('.')-1);
return (a*b).toFixed(len);
}
数值范围
Infinity
正无穷,-Infinity
正无穷
可使用 isFinity()
判断是否有穷,有穷返回 true
利用 Number.NEGATIVE_INFINITY
和 Number.POSITIVE_INFINITY
来获得 -Infinity
和 Infinity
NaN
console.log(NAN == NAN) // false
isNaN() 判断一个值是否 不是数值
。
isNaN(10) // false
isNaN("10") // false, "10"可以转换位10
isNaN('red') // true
isNaN(true) // false, boolean可转换为数子1
Number() 数值转换
-
Boolean值
:true => 1, false => 0 -
Number值
:不变 -
null
:0 -
undefined
:NaN -
String
:"" => 0, '123' => 123, 忽略前导零 '0010' => 10, '1.1' => 1.1, 十六进制 '0xA' => 10, 包含除上述格式外的字符 'ab100cd' => NaN -
Object
:先调用valueOf()
,按上述规则转换,如果为NaN,调用 'toString()', 按上述规则转换
Number('abc') // NaN
Number('10') // 10
Number(0010) // 10
Number(false) // 0
parseInt()
parseInt('1234abc') // 1234
parseInt('abc1234') // NaN
parseInt('') // NaN
parseInt('0xA') // 10
parseInt(22.5) // 22
parseInt('070') // 70,看下面解释
ES5不具有解析八进制的能力,会忽视前导零。
使用 parseInt()
的第二个参数指定解析格式
parseInt('0xA', 16) // 10
parseInt('A', 16) // 10
parseInt('A') // NaN
parseInt('10', 10) // 10
parseInt('10', 8) // 8
parseInt('10', 2) // 2
1.9 String 类型
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 退格 |
\r | 回车 |
\f | 进纸 |
\\ | 斜杠 \ |
\' | 单引号 ' |
\" | 双引号 " |
toString()
null
和 undefined值
没有这个方法
toString()
默认以十进制返回数值的字符串表示,但可以提供一个参数转换成指定的格式
var a = 11;
console.log(a.toString()) // '11'
a = true;
console.log(a.toString()) // 'true'
var n = 10;
console.log(n.toString()) // '10'
console.log(n.toString(2)) // '1010'
console.log(n.toString(8)) // '12'
console.log(n.toString(10)) // '10'
console.log(n.toString(16)) // 'a'
String()
在不知道要转换的值是不是null
和undefined
,可以用 String()
- 如果值有
toString()
方法,则调用它 - 如果值为
null
,返回'null'
- 如果值为
undefined
,返回'undefined'
1.10 Object 类型
var o = new Object();
var o = new Object; // 有效,但不推荐省略圆括号
属性和方法:constructor
, hasOwnProperty()
, isPrototypeOf()
, propertyIsEnumerable()
, toLocaleString()
, toString()
, valueOf
1.11 桉位非,桉位与,桉位或,桉位异或
1.12 有无符号位的左移和右移
P2 变量、作用域和内存问题
2.1 变量
- 基本类型值:简单的数据段 =>
undefined
,null
,boolean
,number
,string
这5种基本数据类型是按值访问
的,因为可以操作保存在变量中的实际的值。 - 引用类型值:保存在内存中的对象。在操作对象时,实际是在操作对象的引用而不是实际的对象。
2.2 复制变量值
如果复制的是基本类型的值,则复制后的结果和原变量是独立的
var a = 1;
var b = a;
console.log(a) // 1
console.log(b) // 1
a = 2;
console.log(a) // 2
console.log(b) // 1
b = 3;
console.log(a) // 2
console.log(b) // 3
如果复制的是引用类型的值,这个值的副本是个指针,复制操作后两个变量将引用同一个对象。
var a = new Object();
var b = a;
a.name = 'hqy';
console.log(b.name) // 'hqy'
2.3 传递参数
注意,访问变量有按值
和引用
两种方式,当时参数只能按值传递
.
- 向参数传递基本类型的值,被传递的值会被复制给一个局部变量(命名参数,或成为arguments对象中的一个元素
- 向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部参数,所以这个局部变量的变化会被反应在函数的外部。
// 传递基本类型的值
function add(num) {
num += 10;
return num;
}
var count = 20;
var result = add(count);
alert(count) // 20,没有变化
alert(result) // 30
// 传递引用类型的值
// 即使这个变量时按值传递的,obj也会按引用来访问同一个对象
function setName(obj) {
obj.name = 'hqy';
}
var a = new Object();
setName(a);
alert(a.name); // 'hqy'
// 以上例子让我们错误地认为参数还是按引用传递的
// 证明对象是按值传递的例子
function setName(obj) {
obj.name = 'hqy';
obj = new Object();
// 上面代码重写obj,现在这个变量引用的是一个局部变量
obj.name = 'sss';
}
var a = new Object();
setName(a);
alert(a.name); // 'hqy'
2.4 检测类型
typeof
在检测基本数据类型时很给力,但检测引用类型的值就没用了。这时候我们就要使用 instanceof
alert(person instanceof Object) // 变量 person 是 Object 吗
alert(person instanceof Array) // 变量 person 是 Array 吗
alert(person instanceof RegExp) // 变量 person 是 RegExp 吗
// 更好的方法
alert(Object.prototype.toString.call(person) === '[object, Array]')
2.5 执行环境和作用域
执行环境
定义了变量或函数有权访问的其他数据,决定他们各自的行为。每个执行环境都有一个与之关联的变量对象
。每个函数都有自己的执行环境。
当代码在一个环境中执行时,会创建对象的一个作用域链
(保证对执行环境有权访问的所有变量和函数的有序访问)。作用域链的前端
,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象
作为变量参数。活动对象最开始只包含一个变量 arguments
延长作用域链
try-catch
语句的 catch
块,with
语句, eval()
function buildUrl() {
var a = 'qwq';
with (location) {
var url = href + a;
}
return url;
}
// with 接受的、是location对象,这个变量被添加到作用域链的前端。引用 href 就是在引用 location.href()
2.6 没有块级作用域
函数中没有用 var
定义变量,这个变量就会被添加到全局环境。外部无法直接获取函数内声明的变量。
如果局部环境中存在同名标识符,就不会使用位于福环境中的标识符。
2.7 垃圾回收
管理内存
function createPerson() {
var name = 'hqy';
return function() {
return name;
}
}
var f = createPerson();
alert(f()); // 'hqy'
// 由于闭包的作用域链中保存着 name,那么意味着这个name占用的内存就永远不会被回收
f = null; // 将 f 设置为 null,减少引用数,确保正常回收其占用的内存
P3 引用类型
3.1 Object 类型
// 构造函数
var a = new Object();
a.name = 'hqy';
a.age = 21;
// 对象字面量,此时不会调用 Object 构造函数
var a = {
name: 'hqy',
age: 21
}
// 访问对象属性
alert(a.name) // 'hqy'
alert(a['name']) // 'hqy' ,方括号内是属性的字符串形式
3.2 Array 类型
创建数组
var a = new Array(20) // 创建一个包含20项的数组
var a = new Array('red', 'blue') // 创建一个包含2项的数组 ['red', 'blue']
var a = ['red', 'blue']; // 建一个包含2项的数组 ['red', 'blue']
var a = []; // 空数组
修改数组
var a = ['red', 'blue'];
a[5] = 'green';
alert(a[2]) // undefined
alert(a.length) // 6
检测数组
value instanceof Array
Array.isArray(value)
Object.prototyoe.toString.call(value) === '[object, array]'
转换方法
var a = ['red', 'blue', 'yellow'];
console.log(a.toString()) // red,blue,yellow 以逗号分隔的字符串
console.log(a.valueOf()) // ["red", "blue", "yellow"] 即数组本身
// toLocaleString() 调用的是每一项的 toLocaleString()
console.log(a.join('||')) // red||blue||yellow 默认是逗号
栈方法
-
push()
接受任意数量的参数逐个添加到数组末尾并返回修改后数组的长度 -
pop()
移除数组最后一项并返回该项
队列方法 -
shift()
移除数组的一项并返回该项 -
unshift()
数组前端添加任意项并返回新数组的长度
重排序
reverse()
反转数组
var a = [1, 2, 3, 4];
console.log(a.reverse()) // [4, 3, 2, 1]
sort()
自定义排序,默认是根据转换成字符串对比每个字符大小,'5' 大于 '10'
// 从小到大
var a = [2, 1, 4, 3];
a.sort(function(a, b) {
return a - b;
})
console.log(a) // [1, 2, 3, 4]
// 给定一个数组 [{name: 'hqy', age: 21}, {name: 'qqq', age: 44}, ...],根据 age 排序
function compare(key) {
return function(obj1, obj2) {
var val1 = obj1[key];
var val2 = obj2[key];
if(val1 < val2) {
return -1;
} else if(val1 > val2) {
return 1;
} else {
return 0;
}
}
}
var a = [{name: 'hqy', age: 21}, {name: 'qqq', age: 44}, ...];
a.sort(compare('age')); // 根据健 age 将数组从小到大排序
数组操作方法
concat()
合并数组,创建新数组,不影响原数组
var a = [1, 2, 3];
var b = a.concat(4, [5, 6]);
alert(a) // 1, 2, 3
alert(b) // 1, 2, 3, 4, 5, 6
slice()
截取字符串,返回新字符串
var a = [1, 2, 3, 4];
var b = a.slice(1, 2);
alert(a) // 1, 2, 3, 4
alert(b) // 2, 3
b = a.slice(1)
alert(b) // 2, 3, 4
splice()
向数组添加或删除内容,改变原数组
// 只是删除
var a = [1, 2, 3, 4];
var b = a.splice(0, 2) // 删除了前两项
alert(a) // 3, 4
alert(b) // 1, 2
// 只是添加
var a = [1, 2, 3, 4];
var b = a.splice(1, 0, 6, 7) // 在位置1了前两项
alert(a) // 1, 6, 7, 2, 3, 4
alert(b) // 空数组
// 既添加又删除
var a = [1, 2, 3, 4];
var b = a.splice(1, 2, 6, 7) // 从位置1删除2项,再在位置1添加2项
alert(a) // 1, 6, 7, 4
alert(b) // 2, 3
位置方法
indexOf()
, lastIndexOf()
迭代方法
可接收4个参数:item
, index
, array
-
every()
:对数组每一项执行给定函数,每一项都返回true,则返回true -
some(0
:对数组每一项执行给定函数,其中一项返回true,则返回true -
filter()
:返回该函数会返回true的项组成的数组 -
forEach()
:对数组每一项执行给定函数,没有返回值 -
map()
:返回每次函数调用的结果组成的数组
归并方法
reduce
, reduceRight
接收4个参数: 前一个值, 当前值,项的索引,数组对象
// 计算给定数组 arr 中所有元素的总和
function sum(arr) {
return arr.reduce(function(prev, cur, index, array) {
return prev + cur;
})
}
3.3 Date 类型
var now = new Date();
var date1 = new Date("2017, 3, 1");
var start = Date.now() // 取得当前时间
var date2 = new Date("2017, 3, 2");
alert(date2 > date1) // true
toString()
, valueOf()
, toLocaleString()
var now = new Date();
console.log(now.toLocaleString());
// 2017/7/1 下午10:13:31
console.log(now.valueOf());
// 1498918470507
console.log(now.toString());
// Sat Jul 01 2017 22:14:17 GMT+0800 (中国标准时间)
3.4 Function 类型
定义函数
// 函数声明
function sum(n1, n2) {
return n1 + n2;
}
// 函数表达式
var sum = function(n1, n2) {
return n1 + n2;
}
函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没什么不同,一个函数可能会有多个名字。
function a(n, m) {
return n + m;
}
alert(a(1, 2)); // 3
var b = a;
alert(b(1, 2)); // 3
a = null; // 将 a 设置为 null,让它和函数断绝关系,但 b 还是正常的
alert(b(1, 2)); // 3
没有重载
function a(n) {
return n * 2;
}
function a(n) {
return n * 3;
}
alert(a(3)) // 9
函数声明和函数表达式
// 函数表达式只有当解析器执行到它所在的代码行,才会真正被解释执行
alert(a) // ReferenceError
var a = function() {
return true;
}
要访问函数的指针而不执行函数的话,必须去掉函数名后的那对大括号。
函数内部属性
-
arguments
: 类数组对象,包含着传入函数的所有参数,只能.length
,不具备数组的其他方法 -
this
: 引用的是函数执行的环境对象
arguments.callee
指向拥有这个arguments
对象的函数 (严格模式下会报错)
var color = 'red';
var o = {color: 'blue'};
function sayColor() {
alert(this.color);
}
sayColor(); // red
o.sayColor = sayColor;
o.sayColor(); // blue
函数属性和方法
每个函数都包含两个属性:length
和 prototype
// length 返回函数希望接收的命名参数个数
function a(n, m) {
return n + m;
}
alert(a.length) // 2
prototype
属性是不可枚举的,因此使用 for-in
无法发现.
每个函数都包含两个非继承来的方法:apply()
和 call()
. 它们第一个参数都是在其中运行函数的作用域,第二个apply
是数组,而call
是要求一个个列举
function sum(n, m) {
return n + m;
}
function applySum(num1, num2) {
// 使用 apply
return sum.apply(this, arguments);
// 使用 call
return sum.apply(this, arguments[0], arguments[1]);
}
var color = 'red';
var o = {color: 'blue'};
function sayColor() {
alert(this.color);
}
sayColor(); // red
sayColor.call(o); // blue
在严格模式下,未指定环境对象而调用函数,则this
不会转型为window
,除非明确把函数添加到某个对象或者调用apply
或call
,否则this
将是 undefied
.
bind()
该方法会创建一个函数的实例,其this
会绑定到传给bind()
函数的值
var color = 'red';
var o = {color: 'blue'};
function sayColor() {
alert(this.color);
}
sayColor(); // red
sayColor.bind(o)(); // blue
3.5 String 类型
replace()
// 第二个参数是函数, 参数依次为匹配项,位置,原始字符串
function htmlEscape(text) {
return text.replace(/[<>"&]/g, function(match, pos, originalText) {
switch(match) {
case '<':
return '<';
case '>':
return '>';
case '&':
return '&';
case '"':
return '"';
}
})
}
3.6 Global对象
诸如 isNaN()
, isFinite()
, parseInt
, parseFloat()
都是 Global
对象的方法
URI 编码方法:encodeURI()
, encodeURIComponent()
, decodeURI()
, decodeURIComponent()
3.7 Math 对象
max()
, min()
舍入方法
-
Math.ceil()
:向上舍入 -
Math.floor()
:向下舍入 -
Math.round()
:四舍五入最接近的整数
random()
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)