# JS 基础
# 主流浏览器内核
浏览器主要由 shell 和内核组成。shell 是浏览器的那些界面,命令,给用户操作的
浏览器 | 内核 |
---|---|
IE | trident |
Chrome | blink |
Firefox | Gecko |
Safari | webkit |
Opera | presto |
# JavaScript 组成
- 核心(ECMAScript)
- 文档对象模型(DOM)--->是针对 XML 但经过扩展用于 HTML 的 API
- 浏览器对象模型(BOM)
&
如果页面中 script
标签中既引入了外部的 js 文件,又嵌入了 js 代码,则嵌入的代码会被忽略
# JavaScript 执行步骤
- 语法分析
- 预编译
- 解释执行
# 变量类型
- 基本类型值(存放在栈里)
- Number
- 浮点数值,保存浮点数值的内存空间是保存整数值的两倍,如 1.0 这样的浮点数会被转换成整数 1
- NaN(非数值),与任何值都不相等
- 判断一个变量是否是 NaN 时,不能用
x == NaN
,而应当用x != x
来判断,只有当x = NaN
时才会返回true
,函数isNaN()
与此类似
- 判断一个变量是否是 NaN 时,不能用
- 数值转换:
Number()
用于任何类型parseInt()
把字符串转换成整数类型,遇到第一个不是数字的字符串停止parseFloat()
把字符串转换成浮点数数类型,遇到第一个不是数字的字符串停止
- 任何类型的数据与 Number 类型进行数学运算时,都会被转换成数字,不能转换成数字的就是
NaN
- String
- 字符串一旦被创建他们的值就不能被改变,如果要改变就必须销毁原来的字符串,再用一个新的来填充该变量
- Boolean
- undefined
- 已声明但未被初始化的变量值为 undefined
- null
- null == undefined 结果为 true
- Number
- 引用类型值(存放在堆里)
- array
- object
- function
- ...
&
基本类型值在栈里面存放数据,变量之间的赋值是通过拷贝副本,此后两个变量可以参加任何操作而不会相互影响;引用类型值存放在堆里,包含引用类型值的变量实际上包含的是指向该对象的指针。
typeof 操作符:检测变量的数据类型
- 返回的值有六种(全是字符串类型)
- 'number'
- 'string'
- 'boolean'
- 'object'
- 'undefined'
- 'function'
typeof(123)
=>'number'
typeof(typeof(123))
=>'string'
- 如果 typeof 返回了
undefined
则有可能是以下三种情况var a = undefined
var b
- 未定义
- 返回的值有六种(全是字符串类型)
instanceof 操作符:检测变量属于哪一种引用类型
- 左操作数是一个对象,右操作数是标识对象的类
- 如果左侧的对象是右侧类的实例,则返回
true
,否则返回false
- 工作原理:
- 为了计算
o instanceof f
- 首先计算
f.prototype
- 然后在原型链中查找
o
- 如果找到,那么
o
就是f
(或者f
的父类)的一个实例,返回true
- 如果
f.prototype
不在o
的原型链中,则o
和f
就没有派生关系,返回false
- 为了计算
- 使用 instanceof 操作符的问题在于:
- 单一的全局环境
- 如果网页中有多个框架,那么就有多个全局环境,就存在多个环境下的构造 函数
- 关于
&&
操作符:
- 大多数情况下都是对表达式进行布尔计算
- 另一种情况:运算符首先计算左侧的值
- 如果为
false
,那么整个表达式也是false
,就不会对右侧的表达式进行计算,这时就返回左侧表达式的值 - 如果为
true
,那么整个表达式就会返回右侧表达式的结果 var p = null
p && p.x // 返回null
- 如果为
i++ 和 ++i
i++ 是先执行表达式语句再运算
++i 是先运算再执行表达式语句
var i = 1 var a = i++ + 1 var b = ++i + 1 a // 2 b // 4
分析:执行第二行语句时,i = 1,所以 a = 2,执行完这个语句,i + 1,所以 i = 2;执行第三行语句时,先把 i + 1,此时 i = 3,最后结果 b = 4
# 相等与全等
- 使用
==
,不同类型的值也可以被看作相等(可以允许类型转换)
类型(x) | 类型(y) | 结果 |
---|---|---|
null | undefined | true |
数字 | 字符串 | x == toNumber(y) |
布尔值 | 任何类型 | toNumber(x) == y |
字符串或数字 | 对象 | x == toPrimitive(y) |
toNumber()
对不同类型返回的结果如下:
值类型 | 结果 |
---|---|
undefined | NaN |
null | 0 |
布尔值 | true = 1,false = 0 |
字符串 | 如果字符串包含字母,返回 NaN,如果是数字组成,返回数字 |
对象 | Number(toPrimitive(obj)) |
toPrimitive()
转换对象时:
如果对象的 valueOf
方法的结果是原始值,返回原始值;如果对象的 toString
方法返回原始值,就返回这个值;其他情况都是错误
- 使用
===
操作符
如果比较的两个值类型不同,比较的结果就是 false;如果值类型相同,就要比较两个值是否一致(引用的同一个对象)
&
所有的大写 ASCII 字母都小于小写的 ASCII 字母
# 类型转换
布尔值的转换
数值类型 | 转换成布尔值 |
---|---|
undefined | false |
null | false |
布尔值 | true/false |
数字 | +0、-0 和 NaN 是 false,其他是 true |
字符串 | 空字符串是 false,其他是 true |
对象 | true |
&
JavaScript 中的任何值都可以转换成布尔值,其中只有六个转换为 false
# 隐式类型转换
隐式类型转换在内部调用的是显示类型转换
isNaN(n)
=>Number(n)
++/--
=>Number()
- 如果
+
运算符的一个操作数是字符串,它会把另一个操作数转换为字符串=>String()
- 四则运算=>
Number()
undifined == null
# 对象转布尔值
所有的对象(包括数组和函数)都将转换为 true,对于包装类型也一样:new Boolean(false)
也将转换为 true
# 对象转字符串和数字
所有的对象都继承了 toString()
和 valueOf()
方法
- toString()
- 作用是返回一个反映这个对象的字符串
({x:1}).toString()
=>[object Object]
[1, 2, 3].toString()
=>1, 2, 3
(function() {}).toString
=>function() {}
- ...
null
和undifined
没有toString()
方法
- valueOf()
- 简单的返回对象本身
- 日期对象会返回 1970/1/1 以来的毫秒数
JavaScript 对象到基本类型的转换经历了以下过程:
- 对象首先会调用
valueOf()
方法,一般对象的valueOf()
方法都会返回这个对象的本身,如果返回的是一个原始值,那么直接将这个结果返回 - 如果返回的不是一个原始值,对象就会去调用
toString()
方法,如果返回的是一个我原始值,就将这个结果返回 - 否则就会抛出异常
&
对于 +
和 ==
运算符,如果其中一个操作数是对象,JavaScript 就会将对象转换为原始值
# Date
var date = new Date();
- getFullYear方法:得到年份
- getMonth方法:得到月份,从0开始计算
- getDate方法:得到日期部分
- getDay方法:得到星期几,0表示星期天
- getHours方法:得到小时部分
- getMinutes方法:得到分钟部分
- getSeconds方法:得到秒部分
- getMilliseconds方法:得到毫秒部分
- getTime方法:得到时间戳
# 垃圾回收机制
# 标记清除(最常用)
垃圾回收器在运行时给所有在内存中的变量都加上标记,然后它会去掉环境中的变量和被环境中的变量引用的变量的标记,而在此之后加上标记的被视为准备删除的变量。
# 引用计数
当声明了一个变量并将引用类型值赋给这个变量,则这个值的引用次数为1;如果这个值又被赋给另一个变量,则引用次数+1;如果引用这个值的变量又取得了另一个值,则引用次数-1,直到引用次数为0,就会被回收。
# 基本包装类型
JS 为了增强原始类型的功能,为 boolean、string、number 分别创建了一个构造函数:
- Boolean
- String
- Number
&
每当读取一个原始类型的时候,后台会通过构造函数创建一个与之对应的原始类型对象,通过这个对象来访问原始类型的属性和方法
引用类型与基本包装类型的主要区别就是对象的生存期:
使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前一直保存在内存中。而自动创建的基本包装类型的对象,只存在于一行代码的执行瞬间,然后立即被销毁。就意味着不能给基本包装类型的对象添加属性和方法
使用new调用的构造函数和直接调用同名的转型函数是不一样的:
var value = "23";
var obj = new Number(value); //构造函数
typeof obj ----> "object"
var number = Number(value); //转型函数
typeof nunber ----> "number"
# 单体内置对象
内置对象:不依赖宿主环境,在程序执行之前就已经存在了
- Global 对象:不属于任何对象的属性和方法最终都是 Global 的
- URI 编码
- encodeURI():使用它编码后的结果是除了空格之外的其他字符都原封不动,只有空格被替换成了 %20
- encodeComponentURI():替换所有非字母数字的字符
- 一般对整个 URI 使用 encodeURI,对附加在 URI 后面的字符串使用 encodeComponentURI
- decodeURI 和 decodeComponentURI 能够对上面两种编码之后的解码
- eval()
- 在
eval()
中定义的代码对当作实际的 ECMAScript 代码来解析,然后把执行结果插入到原来的位置,被执行的代码具有与该执行环境相同的作用域链。 - 在
eval()
中创建的任何变量或函数都不会被提升,只有在执行的时候才创建
- 在
- URI 编码
- Math 对象:
- random()
- 在给定范围内取值:(min,max)max 一般取不到
- value = Math.random() * (max - min) + min
- random()
# 错误处理
# 抛出错误
if(false) {
throw 错误对象;
}
# 捕获错误
try {
//代码块1
}
catch(错误对象) {
//代码块2
}
finally {
//代码块3
}
数组 →