JavaScript学习笔记(一)

参考来源: JavaScript高级程序设计: book.douban.com/subject/105… 千古壹号: github.com/qianguyihao… 小册前端面试之道: juejin.im/book/5bdc71… zh.javascript.info/comparison

简介

JavaScript诞生于1995年, 由web发展初期的Netscape创建, 当时它的出现主要是用于处理网页中的前端验证. 如今JavaScript早已不再局限于简单的数据验证, 而是具备了与浏览器窗口及其内容交互的能力.

一个完整的JavaScript实现应该由三个部分组成:

  1. 核心(ECMAScript)
  2. 文档对象模型(DOM)
  3. 浏览器对象模型(BOM)

JavaScript是由公司开发而成的, 问题是不便于其他的公司拓展和使用. 所以欧洲的这个ECMA的组织, 牵头制定JavaScript的标准, 取名为ECMAScript.
ECMAScript: 是一种由European Computer Manufacturers Association制定和发布的脚本语言规范.
ECMAScript就是对实现该标准规定的各个方面内容的语言的描述, JavaScript实现了ECMAScript, ActionScript同样也实现了ECMAScript. 而不同的浏览器厂商对该标准会有不同的实现.


文档对象模型(DOM)
DOM是针对XML, 但是经过扩展用于HTML的API.
DOM把整个页面映射成为一个多层节点结构. 
DOM级别

  • DOM1级的主要目标是映射文档的结构
  • DOM2级在原有基础上扩充了鼠标和用户界面事件等细分模块
  • DOM3级引入了以统一方式加载和保存文档的方法, 新增了验证文档的方法

浏览器对象模型(BOM)
开发人员使用BOM可以控制浏览器显示的页面以外的部分, 比如让浏览器自动滚动

延迟执行js

  • 使用元素可以指定在禁用脚本的浏览器中显示的替代内容
  • defer属性规定是否对脚本执行进行延迟,直到页面加载为止, 浏览器会先加载没有defer的js.
  • async属性规定一旦脚本可用,则会异步执行
<script type="text/javascript" defer async=true>
	var name = prompt("输入你的名字");
	alert(name);
	document.write(name);
	console.log(name);
</script>
复制代码

规范

标识符不能使用脚本语言中的关键字和保留字
关键字


保留字

其他不建议使用的标识符

代码规范

严格模式

参考来源: developer.mozilla.org/zh-CN/docs/…

可以在整个脚本或函数中开启严格模式, 建议一个函数一个函数地开启严格模式
在函数作用域中使用严格模式: 函数开头写上"use strict"

为什么要使用严格模式:

  1. 减少js代码运行的一些不安全不合理之处, 减少一些怪异行为
  2. 提高编译器效率, 加快运行速度
  3. 为未来新版本的js做好铺垫

数据类型

基本(值)类型

数字number

  • JavaScript不区分整数值和浮点数值, JavaScript中的所有数值均用浮点数值表示.
  • JavaScript能识别十六进制值. 某些JavaScript的实现支持八进制直接量, 有些不支持.
  • JavaScript中的算术运算在溢出, 下溢或被零整除时不会报错Infinity**(-Infinity)表示. 下溢是当运算结果无限接近于0, 这种情况下JavaScript会返回0. 非零数被零整除会返回无穷大或负无穷大, 零除以零会返回一个非数字值(not a number)NaN.
  • NaN和任何值都不相等, 包括它自己. x!=x当且仅当x为NaN时, 结果才为true
  • ECMAScript能够表示的最小数值Number.MIN_VALUENumber.MAX_VALUE**isFinite()**函数可以判断参数是否位于最小值和最大值之间
  • 在js中, 浮点数的运算可能会得到一个不精确的结果(二进制无法精确表示十分之一)
var a = 0.1 + 0.2;
console.log(a); // 0.30000000000000004
复制代码

字符串string
使用加号运算符进行字符串连接
使用s.length得到字符串的长度
字符串中所有的方法实际上返回的是一个新的字符串值

var s = "hello, world";

s[s.length-1]
s.charAt(s.length-1) // 最后一个字符
s.charCodeAt(s.length - 1) // 返回100
String.fromCharCode(65, 66, 67); // 返回'ABC'

s.substring(1, 4) // 截取从位置1到位置3的字符串, 会把负数参数转换为0
s.slice(1, s.length)
s.slice(0, -1) // 如果参数是负数, 比如参数是-3, 则看做s.length-3
s.substr(1, 4) // 第二个参数代表的是截取的长度

s.split(", w") // 根据指定切割字符串

s.replace("l", "a") // 替换
s.replace(/l/g, 'a')

s.indexOf("e") // 字符e首次出现的位置, 返回-1表示找不到
s.lastIndexOf("l") // 字符l最后一次出现的位置
s.indexOf("l", 3) // 从位置3开始查找字符l首次出现的位置

s.toUpperCase()
s.toLowerCase()

s.concat('cxq'); //连接字符串

s.trim() // 去掉字符串前后的空白
复制代码

boolean
undefined, null, 0, -0, NaN, ""都可以被转换成false

undefined

  • undefined是预定义的全局变量, 表示未定义.
  • 对未初始化和未声明的变量执行typeof都会返回undefined
  • undefined和NaN都是全局对象的属性
var message; // 此时message保存的是undefined

console.log(windows.undefined);
复制代码

null
null常用来表示空值.

  • 进行初始赋值时, 可将变量赋值为null
  • 作为垃圾回收时, 可将变量赋值为null

对于 null 来说,很多人会认为他是个对象类型,其实这是错误的。虽然 typeof null 会输出 object,但是这只是 JS 存在的一个悠久 Bug。在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象,然而 null 表示为全零,所以将它错误的判断为 object 。虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来

对象(引用)类型

基本类型的值直接保存在栈内存中, 对象类型是保存到堆内存中.

内置对象
Arguments函数参数集合, Object基础对象, Function函数构造器, Error异常
Date日期, Math数学, RegExp正则 
Array数组, Boolean布尔, Number数字, String字符串

宿主对象
由js的运行环境提供的对象
window, global, document

自定义对象
开发人员自己创建的对象

// 给对象添加属性
var p = {};
p.name = 'brenner';
p['content-type'] = null;

'name' in p // 返回true说明属性名存在
delete p.name; // 删除对象的属性
复制代码

当函数参数是对象类型时

function test(person){
	person.age = 26;
  person = {
  	name: 'yyy',
    age: 30
  };
  return person;
}

const p1 = {
	name: 'ccc',
  age: 25
};

const p2 = test(p1);
console.log(p1, p2);
复制代码

判断类型

typeof

参考来源: jartto.wang/2019/01/17/…

typeof就是判断参数是什么类型的实例, 返回数据类型的字符串表达

// 对未初始化和未声明的变量执行typeof都会返回undefined
typeof name;

var a;
typeof(typeof a); // string

typeof 123; // number
typeof 'hello'; // string
typeof !!' 0'; // boolean
typeof new Function(); // function
复制代码
  • 对于基本类型, 除null以外, 均可返回意料之中的结果
  • 对于引用类型, 除function以外, 一律返回object
  • 对于null, 返回object
  • 对于function, 返回function

instanceof
A instanceof B用来检测A是否是B的实例, 是返回true, 否返回false.
不可用于检测非引用数据类型
如果B的显式原型对象在A的原型链上, 那么A是B的实例, 返回true

s = 'hlslal';
s.split('l') instanceof Array // 返回true

[] instanceof Array; // true
{} instanceof Object; // true
new Date() instanceof Date; // true
复制代码

类型转换

隐式类型转换

10 + '1' // 数字转换成字符串
'2' * '4' // 字符串转换成数字
1 - 'x' // NaN, 'x'无法转换为数字
1+ +'2'+'3' // 返回33

NaN + 'object' // NaN转换为字符串'NaN'
!!x // 等价于Boolean(x)

'0' == 0 // 在比较之前字符串转换为数字
复制代码

显式类型转换

Number('123blue'); // 返回NaN
Number(true); // 1
Number(null); // 0
Number(undefined); // NaN
Number(''); // 0

// 对非string使用parseInt()或parseFloat(), 会先转成string再操作
parseInt("123blue") // 返回123
parseInt("010", 8)
parseInt(true); // 返回NaN
parseFloat("3.14e-7")

var a = false;
String(a);
a.toString();
var a2 = 123;
a2.toString(2); // 转成二进制形式的字符串

Boolean([]) // 返回true
Object(3) // new Number(3)
复制代码

值的比较

字符串间的比较算法

  1. 首先比较两个字符串的首位字符大小
  2. 如果一方字符较大, 则该字符串大于另一个字符串, 算法结束.
  3. 否则, 两个字符串中的字符相等, 继续取出各自的后一位字符进行比较
  4. 重复上述步骤进行比较,直到某字符串率先用完所有字符。
  5. 如果两个字符串同时用完字符,那么它们被判定为相等,否则未结束(还有未比较的字符)的字符串更大

当不同类型的值进行比较时, 它们会首先被转为数字再判定大小.

alert('01' == 1) // 返回true

undefined === undefined // true
null === null // true
NaN == NaN // 返回false

null == undefined // 返回true
null === undefined // 返回false
复制代码

使用严格相等操作符===在进行比较时不会做任何的类型转换.

引用类型

Date

使用来自UTC1970年1月1日零时开始经过的毫秒数来保存日期.

var someDate = new Date("1 25, 2019");
// 等价于
var someDate = new Date(Date.parse("1 25, 2019")); // Date.UTC()的参数是基于0的月份

var start = Date.now(); // 返回表示调用这个方法时的时间的毫秒数
复制代码

基本包装类型

ECMAScript提供了3个基本包装类型(特殊的引用类型): Boolean, Number, String
引用类型与基本包装类型的主要区别就是对象的生存期. 使用new关键字创建的实例, 在执行流离开当前作用域之前都一直保存在内存中. 而自动创建的基本包装类型的对象, 则只存在于一行代码的执行瞬间, 然后立即被销毁.

var s = "abcd";
s.color = "red";
alert(s.color); // undefined

var value = '110';
var num = Number(value);
alert(typeof num); // number

var value = new Number('110');
alert(typeof value); // object
复制代码

Global对象

不属于任何其他对象的属性和方法, 最终都是Global的属性和方法, 诸如isNaN(), isFinite(), parseInt()

eval()方法
当解析器发现代码中调用eval()方法时, 它会将传入的参数当做实际的ECMAScript语句来解析

window对象
web浏览器中, 在全局作用域中声明的所有变量和函数, 都成了window对象的属性

Math对象

方法说明
Math.min()和Math.max()
Math.ceil()执行向上舍入
Math.floor()执行向下舍入
Math.round()执行四舍五入
Math.random()返回介于0和1之间一个随机数

执行上下文

作用域

作用域就是变量和函数可作用的范围. es5只有全局作用域和函数作用域, es6新增块级作用域

全局作用域

  1. 全局作用域在页面打开时创建, 在页面关闭时销毁
  2. 在全局作用域中有一个全局对象window.
  3. 所有window对象的属性和方法.
  4. 全局变量是不会被回收的
  5. 程序最外层定义的函数或变量
  6. 所有未定义直接赋值的变量

函数作用域

  • 调用函数时创建函数作用域, 函数执行完后销毁函数作用域
  • 在函数作用域中也有变量声明提升的特性

块级作用域{}

作用域链

如果变量名和函数名相同时, 函数名优先声明

var a = 10;
function a() {}
console.log(a);
复制代码

函数的生命周期: 分为创建和执行两个时期

var x = 10;
function fn1(){
  console.log(x);
}
function fn2(){
  var x = 20;
  fn1();
}
fn2(); // 10

var x = 10;
function A(){
  var a = 20;
	function B(){
    var b = 30;
  	console.log(a);
  }
}
复制代码

  • 执行环境定义了变量或函数有权访问的其他数据, 每个执行环境都有一个与之关联的对象, 环境中定义的所有变量和函数都保存在这个对象中(我们无法访问这个对象, 但解析器在处理数据时会自动用到它).
  • 某个执行环境中的所有代码执行完毕后, 该环境也随之被销毁, 保存在其中的所有变量和函数定义也随之被销毁.
  • 每个函数都有自己的执行环境. 当执行流进入一个函数时, 函数的环境就会被推入一个环境栈中. 而在函数执行后, 栈将其环境弹出, 把控制权返回给之前的执行环境.

全局执行上下文

  1. web浏览器中, 在执行全局代码之前将window确定为全局上下文
  2. var定义的全局变量赋值为undefined, 添加为window的属性(变量声明提升)
  3. function声明的全局函数添加为window的方法, this赋值为window(函数声明提升)
  4. 最后开始执行全局代码

函数执行上下文

  1. 形参变量赋值为实参, 添加到执行上下文的属性
  2. arguments赋值为实参列表, 添加到执行上下文的属性
  3. var定义的局部变量赋值为undefined, 添加到执行上下文的属性
  4. function声明的函数添加到执行上下文的方法
  5. this赋值为调用函数的对象
  6. 最后开始执行函数体中的代码
var a = 3;
function fn(){
	console.log(a);
  console.log(window.a);
  var a = 4;
}
fn(); // 输出undefined
复制代码

垃圾收集

标记清除

当变量进入环境(例如, 在函数中声明一个变量), 就将这个变量标记为进入环境. 当变量离开环境时, 则将其标记为离开环境.

引用计数

引用计数的含义是跟踪记录每个值被引用的次数.
可能出现循环引用, 比如两个对象互相引用.

异常处理

try-catch-finally语句

如果try块中的任何代码发生了错误, 就会立即退出代码执行过程, 然后接着执行catch块. catch块会接收到一个包含错误信息的对象

function fn() {
	try {
    return 1
  }catch(error) {
    return error.message;
  }finally {
  	return 2;
  }
}
复制代码

错误类型

Error: 其他错误类型都继承自该类型
EvalError: 会在使用eval()函数而发生异常时被抛出
RangeError: 会在数值超出相应范围时触发, 比如let arr = new Array(Number.MAX_VALUE);
ReferenceError: 访问找不到的对象, 不存在的变量时就会发生这种错误
TypeError: 在变量中保存着意外的类型或者访问不存在的方法

抛出错误

throw用于随时抛出自定义错误

转载于:https://juejin.im/post/5ce56dfce51d45775d516ee7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值