犀牛书学习笔记(1):概述及语言核心

把书读薄是学生的本分,把薄的书读厚的是学霸,读薄读厚再读薄,自然就是大师了。

一、概述

  我看的是第六版,由淘宝前端团队出版的《JavaScript权威指南》,犀牛书有很多版本,每一本都非常厚,我没有比较过差异(太多了 ),感觉淘宝前端团队写的还是不错的,全书错误极少,代码写的清晰易懂,内容还设计了CSSHTML5以及jQuery方面的内容,好评!这里的blog只摘录了我在学习过程中觉得比较重要的一些知识点,相当于笔记吧。把书读薄是学生的本分,把薄的书读厚的是学霸,读薄读厚再读薄,自然就是大师了。
我在学习的过程中还看了另外一本关于JavaScript的书《深入理解JavaScript》,此书也是阿里背景,厚度大概是犀牛书的一半。个人感觉书的内容并不像字面那么“深入”,内容讲的不错,但是有点冗余,很多地方都在重复,大体上适合有一定基础的人进阶。
  JavaScript是一门脚本语言,语法相对简单,如今前后端统一的趋势下,深入学习JavaScript是必要的。JavaScript也叫”ECMAScript”,由Brendan Eich整理提出,语言本身和Java的关系并不大,实际上JavaScript借鉴的了多门语言的优点,比如Java的基本语法、原始值和对象机制,Scheme的一类函数,Self的原型继承,PerlPython的字符串、数组和正则表达式。
  JavaScript基于Unicode字符集,虽然html中不区分大小写,但是JavaScript是区分的,举个例在HTML中设置事件处理程序时,可以使用onclick或者onClick,在JavaScript中必须使用小写的onclick。JavaScript的基本语法部分并不难,这里就不再详述了。

二、类型、值和变量

JavaScript的数据类型分为两类:

1. 原始类型

  • 数字:不区分整数值和浮点数值,采用64位表示,16进制以0x开头;
  • 字符串:由单引号或者双引号括起来的一组不可变的字符有序序列;
  • 布尔值:true和false,0、空字符串这些会被转换成false,undefined、null、NaN和false并不相等,除此之外都会转换为true;
  • null:表示数字、字符串或者对象是“无值”的,是空值;
  • undefined:变量的一种取值,表明变量没有初始化或者对象属性不存在;

2. 对象类型

  • 普通对象,被{ }包起来的对象,由key/value对组成;
  • 数组(有序的对象);
  • 函数:包含可执行代码的对象,如果函数用new来初始化一个新建对象,则称之为构造函数,每个构造函数都定义了一个“类”;

JavaScript的变量是无类型的,可以被赋予任何类型的值,也可以重新被赋予其它类型的值,内存回收由语言引擎自动处理,JavaScript的对象和类也是可以动态改变的,语言非常灵活。

Tips:

  1. NaN和任何值都不相等,包括自身,判断是否为NaN的方法是:x!=x(当且仅当x为NaN时返回true);
  2. JavaScript中的字符串是固定不变的,所有破坏性方法返回的都是新字符串;
  3. 存取字符串、数字或布尔值的属性时创建的临时对象称作包装对象
  4. 原始类型的属性都是只读的,也不能给它们重新定义新属性;
  5. 两个单独的对象或者数组永不严格相等();

    1
    2
    3
    4
    var s="hello";
    var S=new String(s);
    s===S; //false
    s==S; //true
  6. JavaScript使用函数作用域,由此引起的闭包非常重要,声明提前机制也值得注意。这里阐述一下我对两者的理解:

    闭包(closure):心理学上有个闭合律,是说人在只看到目标物一部分的情形下,大脑会自动想象出剩余部分,这是我们认知的自然过程。比如你只看到键盘的一角也能很容易地“脑补”出:这是一个键盘。JS中的闭包与此类似:只通过暴露在外的部分接口,也能够获得内部关联的其余变量。具体来说就是函数能够把它周围的变量关联到自己的作用域内,如果全局的变量引用了这个函数,那么函数周围的变量就会一直存在,不会因为离开定义它的函数而被销毁。
    声明提前:JavaScript引擎为了提高执行效率会在程序开始之前进行预处理,预处理阶段会为变量预先分配内存空间以及做一些优化工作。JavaScript的声明提前只是“声明”的提前,具体的定义还是发生在原来定义它的地方。

  7. JavaScript对象的比较是引用的比较,而不是值的比较,对象和其本身相等,但和其他任何对象都不相等;

三、对象

  JavaScript对象类似于静态语言中的结构体,但是是动态的——可以新增属性也可以删除属性。对象包括属性名和属性值,属性名可以是空字符串,但对象中不能存在两个同名属性。属性包含可写、可枚举和可配置三个属性特性。JavaScript中主要有三类对象和两类属性:

  • 内置对象:数组,函数,日期和正则表达式;
  • 宿主对象:由JavaScript解释器所嵌入的宿主环境(比如web浏览器)定义,相当于内置对象;
  • 自定义对象:由运行中的代码创建的对象;
  • 自有属性:直接在对象中定义的属性;
  • 继承属性:在对象原型中定义的属性;

访问对象属性的方法有”[]”和”.”两种,前一种是动态的(可以传入一个变量),后一种是静态的,循环增加属性时必须使用[]方法。属性的delete操作只能删除自有的属性,不能删除继承属性,另外delete只是断开了属性和宿主的联系,如果还有变量引用它,这个属性是不会销毁的,可能会造成内存泄露:

1
2
3
4
var a={p:{x:1}}; 
var b=a.p;
delete a.p;
console.log(b.x); //1

如果要确保销毁一个对象,需要依次遍历删除。
属性检测的三种方法:
| 方法 | 定义 |
| ——– | —–: |
| in | 自有属性或继承属性中包含这个属性则返回true |
| hasOwnProperty | 检测是否为对象自有属性 |
| propertyIsEnumerable | 自有属性且这个属性可枚举时返回true |

get和set

  getter和setter又叫访问器,由它们定义的属性称作存取器属性。定义方法:

1
2
3
4
5
6
7
8
9
10
11
var obj={
get foo(){
return "getter";
},
set foo(val){
console.log("setter: "+val);
}
};
//使用方法
obj.foo="data"; //setter: data
obj.foo; //getter

访问器使得一个属性有两种使用方法,有点类似于重载函数,利用好get和set可以一定程度上简化代码,使程序更具可读性。

JSON

JSON的全称是:JavaScript Object Notation,JavaScript对象表示法。JSON支持对象、数组、字符串、无穷大数字、布尔型和null,但不支持所有的类型(比如函数类型),JS提供两个方法操作JSON对象:JSON.stringifyJSON.parse,分别用来序列化和还原JSON对象。

四、数组

  JavaScript数组最大容纳2的32次方个元素,通常访问数组要比访问对象更快,数组元素可以是任何类型,设置数组的length属性为0可以删除所有元素,使用delete删除数组元素后,该元素的索引也会一并删除,数组长度不变。
常用破坏性和非破坏性的数组方法列表:

破坏性

shift:删除第一个元素,返回该元素
unshift:在首部添加一个元素,返回新的数组长度
pop:删除尾部的一个元素,返回该元素
push:在尾部增加一个元素,返回新数组长度
splice:删除指定位置的n个元素,并插入指定元素,返回被移除的元素
reverse:颠倒数组元素的顺序,返回原数组的引用
sort:数组排序,可传入函数形参,返回原数组引用

非破坏性

concat:创建并返回一个新数组,新数组是所有传入数组连接后的结果
slice:复制指定位置区间的元素组成新数组返回
join:使用指定符号连接数组元素,返回连接后的字符串,默认是’,’
indexOf:查找第一个匹配的结果,返回索引
forEach:遍历数组中的元素,必须传入一个函数,无法提前终止
every和some:所有元素都满足条件则返回true,只要有一个元素满足条件就返回true
map和filter:映射和过滤数组元素