这本由David Flanagan著做,并由淘宝前端团队译的《JavaScript权威指南》,也就是咱们俗称的“犀牛书”,算是JS界公认的“圣经”了。本书较厚(有1004页),读起来颇费功夫,但做为JavaScript(下文简称:JS)相关从业者,我仍是鼎力推荐,必定要读完这本经久不息,好评如潮的JS“圣经”(若是您有耐心的读完,以为还不错的,博客最后附有购买本书的优惠券,可自行领取)。javascript
说完本书重要性,下面重点介绍一下本书做者写书的逻辑性,简单来讲本书分为四部分,第一部分:JS核心;第二部分:客户端JS;第三部分:JS核心参考和第一部分相呼应,是JS核心的重点概括和讲解,也是第一部分的总结和升华部分,因此建议看完第一部分以后能够直接去看第三部分;第四部分:客户端JS参考,和第三方的模式同样,也是第二部分的总结、提炼、讲解已经升华。html
因此总体来讲其实本书能够分为2部分,第一部分:js的核心;第二部分:客户端js;前端
js的核心讲的是js的最基础的逻辑、原理、方法、属性、以及使用;而客户端js和服务器端js,只是做为js语言的一种实践部分,是js语言的一种使用场景,而后在具体场景中一些细化的使用。而本文只是整理了第一部分:JS核心,结合我本身的理解,作一个总结和记录。java
1、JS的类型面试
按照数据类型划分:正则表达式
原始类型:Number、String、Boolean、Null、Undefined、Symbol(ES6加入,它的实例惟一,且不可改变,不能使用关键“new”声明);编程
对象类型:Object数组
扩展:普通的js对象是“命名值”的无序集合,js一样定义了一种特殊对象——数组(array),表示带编号的有序集合。服务器
ES6新出了键控集合:Set和Map,Set集合值惟一,不会重复;Map存储的为键值对。闭包
JS还定义了另外一种特殊对象——函数。若是函数用new来初始化一个新建对象,咱们称为构造函数(constructor),每一个构造函数定义一类对象,除了数组(array)类和函数(Function)类以外,还有日期(Date)类、正则(RegExp)类、错误(Error)类都是js的核心类。
2、JS中的算术运算
算术运算符除了+、-、*、/、%(求余运算符,求整数后的余数)、还有更复杂的运算经过定义Math对象的函数和常量来实现
Math.abs(-10); // => 10:绝对值 Math.ceil(0.6); // => 1.0:向上取整数 Math.floor(0.6); // => 向下取整数 Math.round(0.6); // =>:1.0:四舍五入 Math.random(); // => 0-1随机数 Math.max(1, 3, 5); // => 返回最高值 Math.min(1, -3, 50); // => 返回最低值 Math.pow(2, 3); // => 8:2的3次方 Math.PI; // => π:圆周率 Math.sin(3); // => 3的正弦值 Math.sqrt(30); // => 平方根 Math.tan(100); // => 正切 Math.acos(10); // => 反余弦值 Math.cos(100); // => 余弦值 Math.exp(100); // => e的100次幂
3、string的slice用法
string的slice()用法,提取字符串的一部分,返回一个新字符,不改变原来字符串(和array.slice用法一致)。
var str1 = "hello world"; str1.slice(1, 4); // "ell":截取下标1到下标4,不包含最后一位 str1.slice(1); //"ello world":截取下标1之后的全部字符 str1.slice(-3); //"rld":截取后三位
4、JS中的“假值”
undefined、null、0、-0、""、NaN 这6个能够转换成false的值,称做“假值”。
var exp1 = undefined; if (exp1) { console.log("真"); } else { console.log("假"); } //output:假
5、数字转换的方法(科学技术或四舍五入)
Number转换成字符串的场景提供了三种方法:
var n = 123456.78; n.toFixed(0); //output:123457 n.toFixed(1); //ouput:123456.8 n.toFixed(5); //output:123456.78000 n.toExponential(1); //output:1.2e+5 n.toPrecision(4); //output:1.2346e+5 n.toPrecision(7); //output:123456.8 n.toPrecision(10); //output:123456.7800
6、parseInt()的“高级”玩法
parseInt()能够接收第二个可选参数,这个参数指定了数字转换的基数,有效的取值范围是2-36.
parseInt("11", 5); //6 => 1*5+1 parseInt("ff", 16); //255 => 15*16+15 parseInt("077", 10); //77 => 70*10+7
7、全局变量和"全局属性"的delete
js声明变量使用var和不用var的区别,大部分咱们使用的时候都是同样的,例如:
var str1 = "hello"; str2 = "world!"; console.log("%s %s", str1, str2); //output:hello world!
而在使用delete属性时,使用var的变量是不容许删除的,例如:
var str1 = "hello"; str2 = "world!"; this.str3 = "!!!"; delete str1; //false delete str2; //true delete str3; //true
总结:使用var的变量,能够理解为全局变量,全局变量属性是不可编辑的,而不使用var的能够看作是声明了一个全局属性,等同于this.xxx=yyy,属性是能够编辑的,因此是能够delete的。
8、JS的局部变量提高和块级做用域
先来看代码执行的结果(也是一道经典的js面试题):
var scope = "global"; function f() { console.log(scope); var scope = "local"; console.log(scope); } f(); console.log(scope); //output: undefined、local、global
这是什么缘由形成的?为何不是global/local/global呢?由于es5没有块级做用域,局部变量被提高到最前了声明了,js解析器的机制形成的,上面的代码相似于下面这段代码:
var scope = "global"; function f() { var scope; //只声明变量,变量前置 console.log(scope); scope = "local"; console.log(scope); } f(); console.log(scope); //output: undefined、local、global
因此一般来讲,在做用域里面变量声明的代码要放在代码的最顶部,这是一个很是不错的编程习惯,也能够避免一些没必要要的问题。
9、特殊的Date类型转换
若是我告诉你typeof(new Date()+1)和typeof(new Date-1)的值不一样你信吗?
下面来看具体代码:
var now = new Date(); typeof (now + 1); //output:string typeof (now - 1); //output:number now == now.toString(); //output:true
那上面的问题是怎么形成的,typeof(now+1)不该该是number类型吗?
缘由分析:
“+” 有两种含义,一个是字符串链接,一个是加法。
类型转换的时候,默认先调用valueOf,而后才调用toString,而Date类型除外,因此对于new Date()的时候优先,调用的是toString(),而“+”操做是把他当成了字符串链接而不是数字相加。
“-”的时候,只有减法的含义,也就是说优先调用valuleOf,因此结果为number类
10、js的继承机制
继承机制:js是经过原型链实现继承的。简单实现以下:
function Animal(name) { this.name = name || 'Animal'; this.sleep = function () { console.log(this.name + '正在睡觉!'); } } Animal.prototype.eat = function (food) { console.log(this.name + '正在吃:' + food); }; function Cat() { } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; var cat = new Cat(); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat.sleep()); console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
更多的能够查看阮一峰老师的:Javascript继承机制的设计思想型
11、Array的高级用法
1.slice和splice区别
虽然都是截取数组然而slice和splice的区别很大,接下来具体来看。
先说slice
slice定义:方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。原始数组不会被修改。
var array = ["apple", "banana", "cherry", "dates", "fig"]; array.slice(1, 4); //["banana", "cherry", "dates"] array.slice(1); //["banana", "cherry", "dates", "fig"] array.slice(-2); //["dates", "fig"] console.log(array); //["apple", "banana", "cherry", "dates", "fig"]
//方法经过删除现有元素和/或添加新元素来更改一个数组的内容。 var array = ["apple", "banana", "cherry", "dates", "fig"]; array.splice(2, 2); //从下标2开始截取,截取2个 console.log(array); //["apple", "banana", "fig"]
代码2:
var array = ["apple", "banana", "cherry", "dates", "fig"]; array.splice(2); //从下标2开始截取,截取到最后 console.log(array); //["apple", "banana"]
代码3:
var array = ["apple", "banana", "cherry", "dates", "fig"]; array.splice(2, 2, "plum", "orange"); //截取下标2到后面2个元素替换成"plum", "orange" console.log(array); //["apple", "banana", "plum", "orange", "fig"]
小技巧:可使用var newArray = array.splice();实现数组复制。
2.length的另外一种用法
var array = ["apple", "banana", "cherry", "dates", "fig"]; array.length = 3; //["apple", "banana", "cherry"] array.length = 0; //[] => 删除全部元素
3.reduce()
定义:方法对累加器和数组中的每一个元素(从左到右)应用一个函数,将其减小为单个值。
var array = [10, 5, 20, 15]; var sum = array.reduce(function (x, y) { return x + y }, 0); //求和 var product = array.reduce(function (x, y) { return x * y }, 0); //求积 var max = array.reduce(function (x, y) { return (x > y) ? x : y }); //求最大值
4.every()和some()
定义:数组的逻辑判断,对每个元素进行判断,返回true或者false.
every()每个元素都要知足条件才会返回true,some()其中一项知足条件即会为true.
function fun(element, index, array) { return element > 10; } [2, 5, 8, 1, 4].some(fun); // false [12, 5, 8, 1, 4].some(fun); // true [12, 5, 8, 1, 4].every(fun); // false [12, 15, 18, 11, 14].every(fun); // true
5.map()
定义:将调用数组的每个元素传递给指定的函数,并返回一个新的数组,不会改变老数组。
var array = [1, 4, 9, 16]; var map = array.map(x => x * 2); //[2, 8, 18, 32]
6.Arguments.callee
定义:当前正在执行的函数.
在匿名函数中使用Arguments.callee引用自身,以便实现递归。代码以下:
var fun = function (x) { console.log(x); if (x < 1) { return 1; } return x + arguments.callee(x - 1); } fun(3); //7 => 3+2+1+1
7.sort()排序规则的理解
sort()是能够介绍一个匿名函数做为排序规则的,例如:
var array = [3, 9, 3, 12, 5, 8, 1, 4]; array.sort(function (a, b) { return a - b; }); //[1, 3, 3, 4, 5, 8, 9, 12]
理解:a-b获得一个值,而这个正常的值将按照数字的正常规则进行排序,也就是 负数=>0=>正数,因此理解a-b不能单纯的理解他为一个boolean值,而是根据a-b给数组一个排序规则,若是须要倒叙的话就用b-a.
12、高阶函数
定义: 高阶函数就是操做函数的函数,它接受一个或多个做为参数,并返回一个新函数。
function sum(x, y, f) { return f(x) + f(y); } console.log(sum(-5, 6, Math.abs));
十3、正则表达式字符
[...] 方块内任意字符
[^...] 非方块内任意字符
\w [a-zA-Z0-9]
\W [^a-zA-Z0-9]
\d [0-9]
\D [^0-9]
十4、解构赋值
let [x, y] = [1, 2]; [x, y] = [x + 1, y + 1]; [x, y] = [y, x]; console.log(x, y); // 3 2
十5、闭包
“闭包”这个词刚开始开的时候就头皮发麻,感受很“高大上”难以理解,其实掌握以后,发现也挺好用的,下面介绍一下我对于闭包的理解。
定义:闭包就是能够访问一个函数局部(私有)变量的方法。
var Cat = function () { var name = "cat"; var age = 2; this.getName = function () { return name; } this.getAge = function () { return age; } } var cat = new Cat(); console.log(cat.name); //undefined console.log(cat.age); //undefined console.log(cat.getName()); //cat console.log(cat.getAge()); //2
如上代码:利用闭包能够给用特权的方法访问私有属性,保证了私有变量不被修改和污染,固然根据实际需求能够设置经过方法修改私有属性也是可行的。