1.内存管理
var foo = 'bar' // 分配内存
alert(foo) // 读写内存
foo = null // 释放内存
// example 1
let a = {},
b = '0',
c = 0
a[b] = '麦当劳';
a[c] = '肯德基';
console.log(a[b]) // 肯德基
(1) 堆: 存储引用类型值的空间,一般由开发者分配释放,需要考虑垃圾回收的问题
(2) 栈: 存储基本类型值(Number, String, Boolean, String, Null, Undefined)和指定代码的环境, 由操作系统自动分配释放,存放函数的参数值,局部变量的值等。
存储在栈内存中(16进制内存地址)
属性名不能重复
数字属性名 == 字符串属性名
所以后面的赋值覆盖前面的赋值
最后答案是“肯德基“
2.Example 2
// example 2
let a = {}
b = Symbol('1')
c = Symbol('1')
a[b] = '麦当劳'
a[c] = '肯德基'
console.log(a[b]) // 麦当劳
Symbol() 创建唯一值
Symbol('1')!==Symbol('1')
// 因为Symbol表示独一无二的值
3. Example 3
let a = {}
b = {
n: '1'
}
c = {
n: '2'
}
a[b] = '麦当劳'
a[c] = '肯德基'
console.log(a[b]) // 肯德基
因为属性名不能重复,所以后面的值会覆盖前面的值
4.闭包
(1) 什么是闭包
闭包是函数嵌套函数时,内层函数引用了外层函数作用域下的变量,并且内层函数在全局环境下可以访问,进而形成闭包。
例:
function numGenerator() {
let num = 1
num++
return () => {
console.log(num)
}
}
var getNum = numGenerator()
getNum()
在这个闭包中, numGenerator() 创建了一个变量 num, 接着返回打印num 值的匿名函数,这个函数引用了变量 num, 使得在外部可以通过调用 getNum 方法访问 num, 因此在 numGenerator 执行完毕后,即相关调用栈出栈后,变量 num 不会消失,仍然有机会被外界访问。
闭包的基本原理:
- 在函数中,如果我们返回了另一个函数,且这个返回的函数使用了函数(外层)内的变量
- 外界可以通过这个返回的函数获取原函数(外层)内部的变量值
var test = (function (i) {
return function() {
// console.log(i * 2)
alert(i * 2) // 字符串 4
}
})(2)
test(5)
5.Example4
// example 4
var a = 0, b = 0;
function A(a){
A = function(b){
alert(a + b++)
}
alert(a++)
}
A(1) // "1"
A(2) // "4"
5.深浅克隆
浅克隆: 只复制了引用地址,两者指向同一个内存地址,所以一个值改变了另一个也会跟着改变
let obj2 = {}
for(let key in obj){
if(!obj.hasOwnProperty(key)) break;
obj2[key] = obj[key]
}
console.log(obj, obj2)
// 浅克隆
// es6展开运算符
let obj2 = {
...obj
}
深克隆:
深拷贝是将引用地址和内存地址都复制过来,修改其中一个值另一个值不会改变
// 深克隆
// 函数, 日期, 正则在 JSON.stringify时都会出现问题
let obj4 = JSON.parse(JSON.stringify(obj))
function deepClone(obj){
// 1.过滤特殊情况
if(obj === null) return null
if(typeof obj !== 'object') return obj
if(obj instanceof RegExp){
return new RegExp(obj)
}
if(obj instanceof Date){
return new Date(obj)
}
let newObj = new obj.constructor
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = deepClone(obj[key])
}
}
return newObj
}