基础定义
- 对象是一组无序的集合
- 对象是键值对的集合
正确理解JS对象与Object的关系
- JS对象是JS中七大数据类型之一,这是数据类型层面的叫法
- Object,这个JS对象分支非常有迷惑性
- Function
- Array 以及等等
- Object Function 等等这些叫做类,是JS对象的分支,也代表构造函数,分别能够创建object对象,function对象等等
typeof(42); 'number'
typeof(new Number(42)); 'object'
复制代码
正确访问对象属性
node.style.border ✔
node.style."border" ❌
for(let key in obj){
console.log(obj[key]) √
console.log(obj.key) ❌ <=====> console.log(obj["key"]) 把变量key弄成字符串key了
}
复制代码
对象中的属性名一定是双引号的字符串
当你不写双引号或者写成单引号时JS会为你转化为双引号!
let obj={name:'ryan','age':18}
Object.keys(obj) // ["name", "age"]
复制代码
重要概念
- 如果一个对象不存在一个键名,则会报undefined
- 如果一个对象存在一个键名,但值是undefined,也会报undefined
- 如果一个对象的键名报出null,则说明该键名是存在的,且值也是存在,只不过为null
- 不推荐使用obj.--proto--的操作,因为该隐藏属性在不同浏览器下名字会有不同
var obj={name:undefined};
// 情况1
console.log(obj.bbb) // undefined
// 情况2
console.log(obj.name) // undefined
// 情况3
console.log(obj.__proto__.__proto__) // null
// 如果你实在不信obj.__proto__.__proto__这个属性是存在的,只不过是值为null的话
console.log('__proto__' in obj.__proto__) // true
复制代码
obj.--proto--.--proto-- === null // true
翻译一下:
- --proto--是每个obj存在的一个隐藏属性
- --proto--存放着一个指向名叫prototype原型的地址
- prototype原型存放着所有对象的公有方法
- 每个对象的原型是存在的,这是常识
- 并且原型的原型也是存在的
- 如果不存在,则会报出undefined
- 但是原型的原型是指向null,不是undefined,说明原型的原型是存在的,只不过被人为赋值null
一道重要的题目先检测是否掌握重要的特性
let list = ['name','age','gender'];
let person = {
name:'frank',age:18,gender:'man'
}
for (let i=0;i<list.length;i++){
let name=list[i]
console.log(person___???___)
// 这里应该A: console.log(person.name)
// 还是B: console.log(person[name])
}
复制代码
对象键名会转化成字符串
输入的值会在内部转化一下
var obj={2:2} // chrome欺骗你让你以为你输入的数字2在对象内也是数字
Object.keys(obj) // 原形毕露 ["2"]
var obj={1e2:2,0xFF:100}
Object.keys(obj) // 先转成数字100再转成字符串'100'
复制代码
用变量当作对象的键名
var a=123; // 看似a是123数字
var obj={[a]:123}; // 实际a是'123'字符串
Object.keys(obj)
var obj={[1+2+3]:123}; // 还支持js表达式,最终是转成字符串
Object.keys(obj)
复制代码
// 以上的新写法等价于老写法:
var a=123;
var obj={}
obj[a]=123;
Object.keys(obj)
复制代码
每个对象都有一个隐藏属性--proto--
var obj={123:123};
obj.toString(); //这个方法哪来的呢?
复制代码
- 隐藏属性--proto--存着一个地址
- 这个地址指向存储着公有方法的地方
- 这个地方叫prototype原型
'keyName' in obj 与 obj.hasOwnProperty('keyName') 的区别
- 'keyName' in obj 会逐一排查原型链
- obj.hasOwnProperty('keyName') 不会排查原型链,只会检查自身
let prototypeObj={name:'ryan'};
let obj=Object.create(prototypeObj); // 篡改了原型链并创建了新对象obj
'name' in obj; // true 因为顺着原型链找到obj.__proto__
'toString' in obj; // true 因为顺着原型链找到obj.__proto__.__proto__
obj.hasOwnProperty('name'); // false
复制代码
增删改查
增改
批量赋值
let obj={};
Object.assign(obj,{p1:1,p2:2,p3:3,p4:4});
console.log(obj);
复制代码
如何修改对象上的公有属性
let obj={};
obj.__proto.toString=123; // 不推荐,因为隐藏属性在不同浏览器中名字不同
window.Object.prototype.toString=123; // 推荐
复制代码
如何修改一个对象的原型链 或者说修改隐藏属性
let obj={},prototypeObj={name:'ryan',gender:'male'};
obj.__proto__=prototypeObj; // 不推荐
console.log(obj)
复制代码
点击箭头逐一展开可以看到
- obj自身为空
- obj.--proto--被人为篡改为obj1
- obj.--proto--.--proto--才能真正调用到原本为篡改前的toString()
let obj = Object.create() 创建一个对象并指定其原型
obj.--proto-- = obj1 可以做到但是不推荐
// 推荐做法
let prototypeObj={name:'ryan',gender:'male'};
let obj=Object.create(prototypeObj); // 把prototypeObj替换原有的__proto__并创建新对象obj
console.log(obj);
Object.assign(obj,{person:1}); // 批量创建obj的属性
console.log(obj);
复制代码
查(Object.keys/values/entries() )
- keys 看键名
- values 看值
- entries 看键与值
如何查看对象拥有的prototype中的公有属性
console.dir(obj)
如何判断属性是私有的还是公有的?
obj.hasOwnProperty('toString') // false
obj.__proto__.hasOwnProperty('toString') // true 在原型prototype上当然是自身的
复制代码
查看键名对应的值
- obj['keyName']
- obj.keyName
- obj[keyName] // 这是错误的 这里keyName是一个变量名
var name='123'
var obj={};
obj[console.log(name)];
// 会得到undefined,过程如下:
// console.log()永远返回undefined
// 然后obj[]会自动把undefined===> 'undefined'
// obj['undefined'] 没有的键名当然返回undefined
复制代码
删(delete操作符通常只删属性名)
删除对象中的一组键值对以下两种方式
- delete obj.xxx
- delete obj['xxx']
var obj={name:'ryan',gender:'male'};
obj.name=undefined;
console.log(obj);
delete obj.name; // 方式1
console.log(obj);
delete obj['gender']; // 方式2
console.log(obj);
'name' in obj; // in 的操作 用于判断对象中是否存在'name'这个属性名
复制代码
obj.oneKeyName === undefined 返回true的话 会有个坑
// 可能存在以下两种情况
var obj={}
obj.oneKeyName === undefined // true 情况1
var obj={ oneKeyName:undefined }
obj.oneKeyName === undefined // true 情况2
复制代码
- 对象自身不存在这个键名时,会返回undefined
- 对象自身存在这个键名时,但值确实为undefined
- 但作为程序员肯定是要 分清楚到底是情况1还是情况2的,
- 因此obj.oneKeyName === undefined这个方式分不清
那么如何去判断一个对象存在一个键名,且值是undefined呢?
var obj={name:'ryan'};
'name' in obj && obj.name === undefined
复制代码