一. 对象基础
创建:
let user = new Object(); //"object constructor" syntax
let user = {} // "object literal" syntax
let user ={
"likes birds":true //key值有多部分需要用引号括起来
}
增加:
user["name"]="value"
user.name = "value"
删除:
delete user.name
计算属性:
let fruit = prompt("Which fruit to buy?", "apple");
let bag = {
[fruit]:5
}
或者
let bag[fruit] = 5;
属性简写
funciton makeUser(name, age){
return {
name,
age
}
属性检查
key in obj
obj.key === undefined ?
第二种方法有个缺陷,当给obj.key赋值undefined时,则返回false
遍历
fot (let key in obj)
遍历顺序
整数属性被升序排列,其他类型的按照创建顺序排列。整数属性包括被转换成整数后形态不变的。比如: “1”,“23” 而不是 “+1”, “+23”,“1.2”。为了防止排序可做如下操作
let codes = {
"+49": "Germany",
"+41": "Switzerland",
"+44": "Great Britain",
// ..,
"+1": "USA"
};
for(let code in codes) {
alert( +code ); // 49, 41, 44, 1
}
引用传递
原型类型的复制通过值复制的形式传递,即将原值赋给新变量。
对象类型的复制通过传递引用地址传递,即将对象在内存中的存储地址的引用传递给新变量,并不会重新生成对象。
对象复制
Object.assign(dest[,src1,src2...])
此方法为浅克隆,当对象中含有对象时,此时新对象中的该对象对应的key指向旧对象的内存地址。
二. 垃圾回收机制
内存生命周期
1.分配需要的内存
2.使用分配到的内存(读写)
3.不需要该内存时释放内存
垃圾回收
垃圾回收算法主要依赖于引用的概念。一个对象如果有访问另一个对象的权限(隐式或显式),叫做一个对象引用另一个对象。
引用计数垃圾收集算法
核心:将“对象是否不再需要”定义为“对象有没有被其他对象引用到”如果没有引用指向该对象,则对象将被回收。
缺点:无法处理循环引用
下面例子中,两个对象被创建并互相引用,形成循环。他们被调用之后会离开函数作用域,所以已经没用可以被回收。然而引用计数法考虑到他们互相有至少一次引用,所以不会被回收
function f(){
var o = {};
var o2 = {};
o.a = o2; // o 引用 o2
o2.a = o; // o2 引用 o
return "azerty";
}
f();
标记清除算法
核心:将“对象是否不再需要”简化定义为“对象是否可以获得”,嘉定设置一个叫做root的对象,垃圾回收器将定期从root开始,找所有被root引用的对象,然后找这些对象引用的对象…从根开始,垃圾回收期将找到所有可以获得的对象和不能获得的对象。当函数调用返回之后,从全局对象无法引用到,因此解决了循环引用的问题。
root:
1.当前函数的局部变量和参数
2.当前函数嵌套链上的函数的局部变量和参数
3.全局变量
后续补充:
lodash深度克隆
三. 对象转基本类型
在对象需要转换为基本类型的环境下,上下文会提供一个称为“hint”的转化参数,根据转换参数选择不同的转换算法。(所有对象转换为boolean都是true)
1.string
2.number
3.default:既会tostring 也会tonumber,通常情况下和number转换逻辑一样。
根据“hint”值转换过程将采取以下过程:
1.调用obj[Symbol.toPrimitive](hint),如果存在的话。
2.如果hint为string,尝试调用obj.toString() 然后obj.valueOf()
3.如果hint为number或default,尝试调用obj.valueOf()然后obj.toString()
实现toString 或 valueOf时 要求返回值必须是基本类型,否则将会被忽略掉
实现obj[Symbol.toPrimitive]时 要求返回值必须是基本类型,否则将会报错。
四. 构造器,new
构造方法
构造方法就是普通的方法,但是通常有两点规范:
1.方法名首字母大写(人为规定)
2.用new关键字调用
new
使用new调用方法时有如下步骤:
1.创建一个空对象,并将this指向该对象。
2.函数体执行。
3.返回this对象。
function User(name) {
// this = {}; (implicitly)
// add properties to this
this.name = name;
this.isAdmin = false;
// return this; (implicitly)
}
当构造函数无需重复使用的时候也可采用new+匿名函数的方式创建
let user = new function() {
this.name = "John";
this.isAdmin = false;
// ...other code for user creation
// maybe complex logic and statements
// local variables etc
};
在构造函数中可调用new.target判断构造函数是否通过new关键字调用,如果不是则返回undefined,是则返回构造函数。
重写构造函数return
如果return返回对象类型,则会取代默认返回的this对象。
如果返回基本类型,则仍旧返回默认的this。