《JavaScript权威指南》读书笔记——JavaScript核心
前言
这本由David Flanagan著作,并由淘宝前端团队译的《JavaScript权威指南》,也就是我们俗称的“犀牛书”,算是JS界公认的“圣经”了。本书较厚(有1004页),读起来颇费功夫,但作为JavaScript(下文简称:JS)相关从业者,我还是鼎力推荐,一定要读完这本经久不息,好评如潮的JS“圣经”(如果您有耐心的读完,觉得还不错的,博客最后附有购买本书的优惠券,可自行领取)。
说完本书重要性,下面重点介绍一下本书作者写书的逻辑性,简单来说本书分为四部分,第一部分:JS核心;第二部分:客户端JS;第三部分:JS核心参考和第一部分相呼应,是JS核心的重点归纳和讲解,也是第一部分的总结和升华部分,所以建议看完第一部分之后可以直接去看第三部分;第四部分:客户端JS参考,和第三方的模式一样,也是第二部分的总结、提炼、讲解已经升华。
所以整体来说其实本书可以分为2部分,第一部分:js的核心;第二部分:客户端js;
js的核心讲的是js的最基础的逻辑、原理、方法、属性、以及使用;而客户端js和服务器端js,只是作为js语言的一种实践部分,是js语言的一种使用场景,然后在具体场景中一些细化的使用。而本文只是整理了第一部分:JS核心,结合我自己的理解,做一个总结和记录。
正文
一、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的核心类。
二、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次幂
三、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":截取后三位
四、JS中的“假值”
undefined、null、0、-0、""、NaN 这6个可以转换成false的值,称作“假值”。
var exp1 = undefined;
if (exp1) {
console.log("真");
} else {
console.log("假");
}
//output:假
五、数字转换的方法(科学技术或四舍五入)
Number转换成字符串的场景提供了三种方法:
- toFixed() => 根据小数点后指定位数将数字转化成字符串,会进行四舍五入;
- toExponential() => 使用指数计数法将数字转换为字符串;
- toPrecision() => 根据指定的有效字位数将数字转换成字符串;
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
六、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
七、全局变量和"全局属性"的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的。
八、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
所以通常来说,在作用域里面变量声明的代码要放在代码的最顶部,这是一个非常不错的编程习惯,也可以避免一些不必要的问题。
九、特殊的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类
十、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继承机制的设计思想型
十一、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.
十二、高阶函数
定义: 高阶函数就是操作函数的函数,它接受一个或多个作为参数,并返回一个新函数。
function sum(x, y, f) {
return f(x) + f(y);
} console.log(sum(-5, 6, Math.abs));
十三、正则表达式字符
[...] 方块内任意字符
[^...] 非方块内任意字符
\w [a-zA-Z0-9]
\W [^a-zA-Z0-9]
\d [0-9]
\D [^0-9]
十四、解构赋值
let [x, y] = [1, 2];
[x, y] = [x + 1, y + 1];
[x, y] = [y, x];
console.log(x, y); // 3 2
十五、闭包
“闭包”这个词刚开始开的时候就头皮发麻,感觉很“高大上”难以理解,其实掌握之后,发现也挺好用的,下面介绍一下我对于闭包的理解。
定义:闭包就是可以访问一个函数局部(私有)变量的方法。
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()); //
如上代码:利用闭包可以给用特权的方法访问私有属性,保证了私有变量不被修改和污染,当然根据实际需求可以设置通过方法修改私有属性也是可行的。
《JavaScript权威指南》读书笔记——JavaScript核心的更多相关文章
- Javascript权威指南——读书笔记
一.JavaScript核心语法 1.字符串中接受RegExp参数的方法 (1)text.search(pattern)返回首次匹配成功的位置 (2)text.match(pattern)返回匹配组成 ...
- JavaScript权威指南读书笔记
JavaScript 1.变量 变量是一个表示值的符号,是一个名字,他的本质是值: var x; //----声明一个变量: 值通过等号“=”赋给变量,x = 16; 对象是名/值对的集合,或字符串到 ...
- JavaScript权威指南读书笔记【第一章】
第一章 JavaScript概述 前端三大技能: HTML: 描述网页内容 CSS: 描述网页样式 JavaScript: 描述网页行为 特点:动态.弱类型.适合面向对象和函数式编程的风格 语法源自J ...
- JavaScript 权威指南-学习笔记(一)
本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! ## JavaScript 权威指南-学 ...
- JavaScript权威指南学习笔记6
这两天主要翻看了书中的第18-22章,重点看了第17章:事件化处理,其它几章节主要是翻了下书知道有相关的概念,没有真正理解其中的内容,或者没有考虑究竟如何能把里面的内容应用到实际的项目中.说的讽刺一点 ...
- Javascript权威指南阅读笔记--第3章类型、值和变量(1)
之前一直有个想法,好好读完JS权威指南,便于自己对于JS有个较为全面的了解.毕竟本人非计算机专业出生,虽然做着相关行业的工作,但总觉得对于基础的掌握并没有相关专业学者扎实,正好因为辞职待业等原因,还是 ...
- HTTP权威指南读书笔记
HTTP权威指南笔记 读书有两种境界,第一种境界是将书读薄,另一种是读厚.本篇文章就是HTTP权威指南的读书笔记,算是读书的第一重境界,将厚书读薄.文章对HTTP的一些关键概念做了比较详细的概述,通读 ...
- css权威指南读书笔记
今天翻手机,翻到了许久之前看css权威指南时的笔记,遂移到博客中来. 1.属性选择器p.one class名为one的p元素p[class][name] 含有class和name属性的p元素p[cla ...
- 经典的性能优化最佳实践 web性能权威指南 读书笔记
web性能权威指南 page 203 经典的性能优化最佳实践 无论什么网络,也不管所用网络协议是什么版本,所有应用都应该致力于消除或减 少不必要的网络延迟,将需要传输的数据压缩至最少.这两条标准是经典 ...
- css权威指南读书笔记-第10章浮动和定位
这一章看了之后真是豁然开朗,之前虽然写了圣杯布局和双飞翼布局,有些地方也是模糊的,现在打算总结之后再写一遍. 以下都是从<css权威指南>中摘抄的我认为很有用的说明. 浮动元素 一个元素浮 ...
随机推荐
- (笔记):组合and继承之访问限制(一)
下面在介绍组合与继承之前,先介绍一下访问限制,访问限制:public.protected.private三者是按照授权的大小排序的.这里有个博客,对这三者有了经典的诠释.http://blog.csd ...
- cobbler安装配置.基本全了多看help和docs
env 系统环境配置,软件包安装 centos7 yum update -y sed -i s/SELINUX=enforcing/SELINUX=disabled/g /etc/sysconfig/ ...
- Python模块学习---Web
import urlparse url = urlparse.urlparse("http://www.python.org/doc/FAQ.html") print url pr ...
- windows 下进程池的操作
在Windows上创建进程是一件很容易的事,但是在管理上就不那么方便了,主要体现在下面几个方面: 1. 各个进程的地址空间是独立的,想要在进程间共享资源比较麻烦 2. 进程间可能相互依赖,在进程间需要 ...
- 生成器&迭代器
通过列表生成式,我们可以快速创建一个列表,但是受到内存的限制,列表容量是有限的,而且一个包含100万个元素的列表不仅占用很大的存储空间,如果我们仅仅需要访问当前几个元素,那后面绝大多数元素占用的空间都 ...
- git删除本地分支
远端master分支有更新需要拉取至本地,但是代码有些地方做了修改导致了小冲突,但是这些修改又是无关紧要的,于是就打算直接删除掉本地分支再重新拉取master分支,过程如下: //查看本地分支 git ...
- Gym 101667I Slot Machines
原题传送门 题意:给定n(n≤106)个数,要求将它化为混偱环小数的形式,即前k个数不参与循环,之后所有数以p为循环节长度进行循环.求k和p,要求k+p尽量小,k+p相等时要求p尽量小. 样例1 输入 ...
- BZOJ 1597: [Usaco2008 Mar]土地购买【斜率优化+凸包维护】
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4989 Solved: 1847[Submit] ...
- 最小生成树—prim算法
最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...
- chorme浏览器的Access-Control-Allow-Origin拦截限制
今天在公司调试一个项目,这个项目的前后端是分离开的,也就是说前后端是在两个站点上的.我负责的前端页面在请求后端数据的时候数据可以拿到,但是chrome安全级别高,自动拦截跨域和站点的数据请求及交互,出 ...