四则运算
// 只有当加法运算时,其中一方是字符串类型,就会把另一个也转为字符串类型。其他运算只要其中一方是数字,那么另一方就转为数字。
console.log(1 + '1') // '11' 加法只要一方是字符串,就会将另一方转化为字符串
console.log(+ '1') // 1 + 具有转义的作用,只有+的时候,会将之后转为number类型
console.log(+ 'a') // NAN Number('a') => NaN
console.log(1 + + '1') // 2
console.log('1' + + '1') // '11'
console.log('a' + + 'b') // 'aNaN'
console.log(1 + !0) // 2 ! 的优先级高于+ 所以会先计算!0 结果为true 1 + true => 2
console.log(1 + !1) // 1
== 操作符
// == 操作符
console.log(NaN == NaN); // false == 操作符 会将两侧数据的typeof转换 NaN是number类型 但是不会相等
console.log(0 == -0); // true
console.log(null == undefined); // true
console.log(1 == '1'); // true 数字和字符串比较,会将字符串转换为数字
console.log(1 == false); // false 数字和布尔值比较,会将布尔值转换为数字
console.log(0 == {}); // false 对象比较时,会先转化为基本类型,空对象会转为[object object],所以typeof ({})的值为NaN
console.log(0 == []); // true typeof ([])的值为'' 字符串又会被转化为数字
console.log([] == ![]); // true !的优先级高 ![]的值为true [] == false => [] == 0 => '' == 0 => 0 == 0
// 对象转普通类型会经过两个过程
function toPrimitive (obj) {
if (obj.valueOf()) return obj.valueOf()
if (obj.toString()) return obj.toString()
}
toPrimitive({a: 1});
执行上下文
https://yanhaijing.com/javascript/2014/04/29/what-is-the-execution-context-in-javascript/
[ ] 种类
- [ ] 全局上下文 => 首次加载会默认执行
- [ ] 函数上下文 => 函数调用时会执行
[ ] 要点
- [ ] 单线程
- [ ] 同步执行
- [ ] 一个全局上下文
- [ ] 无限制函数上下文
- [ ] 每次函数被调用创建新的执行上下文,包括调用自己
b() // call b console.log(a) // undefined var a = 'Hello world' function b() { console.log('call b') }
脚本运行首先会默认创建
全局上下文
放入栈顶,值为undefined
,在调用b方法的时候,创建了函数执行上下文console.log('call b')
放入栈顶,一旦上下文执行完毕,它将被从栈顶弹出,并将控制权返回给下面的上下文,直到只剩全局上下文能为止。b() // call b second function b() { console.log('call b fist') } function b() { console.log('call b second') } var b = 'Hello world'
在提升的过程中,相同的函数会覆盖上一个函数
闭包
[ ] 什么是闭包?
- [ ] 函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包。
function A() { let a = 1 function B() { console.log(a) } return B }
[ ] 闭包的作用是什么
- [ ] 减少全局变量的产生,起到隔离的作用,使一个方法可以访问另一个方法中的变量
[ ] 闭包的缺点是什么
- [ ] 产生的变量不被销毁,不被使用,容易引起内存泄漏
[ ] 如何解决闭包的缺点
- [ ] 使用后将闭包赋值为null
// 闭包 function other () { let a = 1; function closure () { // closure是一个闭包 a++; console.log(a); } return closure } let bus = other(); // 接受闭包 bus(); // 执行 bus(); bus = null; // 销毁
深浅拷贝
延伸阅读:
基本类型存储在栈中,对象存储在堆中,
let b = {a: 1}
时,b存储于栈中,他指向堆中的对象
let a = {
age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2
如果给一个变量赋值一个对象,那么两者的值会是同一个引用,其中一方改变,另一方也会相应改变。
[ ] 浅拷贝
- [ ]
Object.assign
let a = { age: 1 } let b = Object.assign({}, a) a.age = 2 console.log(b.age) // 1
- [ ] 展开运算符(…)
let a = { age: 1 } let b = {...a} a.age = 2 console.log(b.age) // 1
- [ ]
[ ] 深拷贝
- [ ]
JSON.parse(JSON.stringify(object))
let a = { age: 1, jobs: { first: 'FE' } } let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'native' console.log(b.jobs.first) // FE
会忽略
undefined
不能序列化函数
不能解决循环引用的对象
- [ ]