学习数据类型时,学过了object类型,知道了它是对象类型
但是没有深入了解,现在开始深入了解你的对象
创建对象
字面量
const obj = {
name: "枫枫"
}
new一个对象
const o2 = new Object({})
原型对象
function People(name, age){
this.name = name
this.age = age
}
People.prototype.eat = function (){
console.log(`${this.name}在吃饭`)
}
const o2 = new People("枫枫", 21)
console.log(o2)
o2.eat()
create方法
继承
// 其中的name和age属性 是在原型上
const o3 = Object.create({name: "枫枫", age: 21})
console.log(o3)
console.log(o3.name)
o3.name = "lisi"
// 给自己加了一个name属性
console.log(o3.name)
// 如果自己有这个属性,就用自己的,没有就去原型上去找
属性操作
查询,通过点或者方括号获取
console.log(o3.name)
console.log(o3["name"])
删除属性 delete,只能删除自身的,继承来的不能删
delete o3.name // 只能删自己身上的属性
delete o3.age
// 原型上的name和age还在
检测属性
in, 可以自己+检测继承来的属性
const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log("age" in o3) // true
console.log("addr" in o3) // true
console.log("eat" in o3) // true 方法就是特殊的属性
hasOwnPreperty 检测自身的属性
const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log(o3.hasOwnProperty("addr")) // true
console.log(o3.hasOwnProperty("age")) // false
属性枚举
for-in,继承+自身的属性
const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
for (const o3Key in o3) {
console.log(o3Key)
}
Object.keys() 自己的属性
const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log(Object.keys(o3)) // ["addr"]
Object常用的API
Object.assign() 浅拷贝
Object.assign(target, ...sources)
// 参数:target 目标参数,sources源对象 返回值:目标对象
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。
Object.assign方法只会拷贝源对象自身的并且可枚举的属性到目标对象。assign其实是浅拷贝而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。同名属性会替换。
const obj = {name: "王五", addr: "长沙"}
const source = {
name: "枫枫",
info: {
age: 21
},
likes: []
}
Object.assign(obj, source)
source.info.age = 22 // 最终会影响到 obj里面的age
source.name = "zhangsan" // 外层的不会影响
source.likes.push("篮球") // 最终会影响到 obj里面的likes
console.log(obj)
Object.keys()
一个表示给定对象的所有可枚举属性的字符串数组。
const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log(Object.keys(o3)) // ["addr"]
getOwnPropertyNames()
Object.getOwnPropertyNames() 返回一个数组,该数组对元素是对象自身拥有的枚举或不可枚举属性名称字符串。
const o1 = {name: "枫枫"}
Object.defineProperty(o1, "age", {
value: 21,
writable: true, // 是否可修改
enumerable: false, // 是否可枚举
configurable: true, // 是否可删除
})
console.log("Object.keys", Object.keys(o1)) // 获取可枚举的属性列表
console.log("Object.getOwnPropertyNames", Object.getOwnPropertyNames(o1)) // 获取属性列表
defineProperty定义对象属性
Object.defineProperty(obj, "name", {
value: 101,
writable: true, // 是否允许修改
enumerable: true, // 是否允许枚举
configurable: true, // 是否允许删除
});
原型与原型链
原型在JavaScript是一个很重要的概念,它是面向对象可以继承的基础。
原型链是原型的查找机制,是一条寻址链。其实原型上的方法或属性查找,都是按照一定的顺序沿着原型链进行查找的。如果查找到最后仍然没有找到这个原型和方法,那么就真的没有了
原型链的尽头是null
给构造函数添加原型
使用prototype
const obj = {}
console.log(obj)
const o1 = new Object({})
Object.prototype.name = "枫枫"
console.log(o1)
修改现有对象的原型
找这个现有对象的父级的构造函数
比如{}的原型是Object的实例
const obj = {}
Object.prototype.toString = function (){
return "这是对象的toString方法"
}
console.log(obj + "")
console.log(obj.toString())
Object.create()设置原型方法
const o2 = Object.create({
eat(){
console.log("吃饭")
}
})
console.log(o2)
使用__proto__属性
可以通过设置对象的 __proto__ 属性来改变其原型
const o2 = Object.create({
eat(){
console.log("吃饭")
}
})
o2.__proto__.study = function (){
console.log("在学习")
}
console.log(o2)
new的过程
- 创建一个新的对象
- 把该对象的__proto__属性设置为构造函数的prototype属性,即完成原型链
- 执行构造函数中的代码,构造函数中的this指向该对象(obj)
- 返回该对象obj
function People(name){
this.name = name
}
function _new(fn, ...args){
// 1. 创建一个新的对象
const o = {}
// 2. 把该对象的__proto__属性设置为构造函数的prototype属性,即完成原型链
o.__proto__ = fn.prototype
// 3. 执行构造函数中的代码,构造函数中的this指向该对象(obj)
fn.apply(o, args)
// 4. 返回对象
return o
}
const o3 = new People("枫枫")
console.log(o3)
const o4 = _new(People, "枫枫")
console.log(o4)