JS 对象(Object)的深入解析—私有属性

当你走的很远的时候,回过头来看看自己走过的道路,可能会发现曾错过的风景。

JS中万物都是对象,今天就深度讲一下Object的里面到底有什么。文章主要讲对象的自有属性和原型中的属性,至于原型链就不在这篇文章多讲了。

一、Object简述

创建对象的方法有如下几种

  1. new + Object
  2. 字面式 {name: 'vinter'}
  3. 工厂模式(可以创建多个对象)
let person = (name, age) => {
  let o = new Object()
  o.name = name
  o.age = age
  Object.prototype.say = () => {
    console.log('你好')
  }
  return o
}
let p1 = person('vinter', 18)
let p2 = person('xzwen', 20)
//  无法识别对象类型 都是Object
  1. 构造函数
function Person(name){
    this.name = name
        this.say = () => {}
}

let p = new Person('vinter')

console.log(p instanceof Person)  // true
console.log(p instanceof Object)  //  true
//  能够识别对象的类型
  1. 原型模式
function Person(name){
}
Person.prototype = {
  name: 'viter',
  age: 18,
  say: () => {}
}
let p = new Person()

//  所有属性写进原型,对象都能访问,没有对象的私有属性
  1. 混合模式
    \color{red}{最优方法} 实例拥有自己的私有属性,又拥有共同的原型方法
function Person(name, age){
    this.name = name
    this.age = age
}
Person.prototype = {
  constructor: Person,  //  将constructor 指向Person
  say: () => {console.log('你好')}
}
let p = new Person('vinter', 18)
console.log(p.name)
p.say()

二、Object私有属性解析

object.png

1. Object.assign

Object.assign() 方法用于将其他对象的可枚举属性复制到目标对象(即第一个参数对象)

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const sources = { d: 2, b: 6 }
Object.assign(target, source, sources)
//  { a: 1, b: 6, c: 5, d: 2}

console.log(target.c)
//  5

常用于将某个对象合并到新对象{}。

Object.assign({}, source)

2. Object.create

Object.create =  function (obj) {
    var F = function () {};
    F.prototype = obj;
    return new F();
};

常用于继承某个构造函数的原型属性,但是不能继承该构造函数的实例属性,例如上面例子

let P = () => {}
p.prototype = obj
let p1 = Object.create(obj)

3. Object.defineProperty

Object.defineProperty(obj, prop, descriptor)

该属性是实现vue双向数据绑定的核心,这里主要讲它的使用方法。
讲它的相关用法时,就得先理解\color{red}{数据属性和访问器属性}的概念。
1.数据属性
数据属性的四个特性
configurable:表示是否能被delete删除属性且能重新定义该属性。
enumerable:表示能否通过for-in遍历的属性。
writable:表示是否能修改属性。
value:属性的值。

let person = {
    name: 'vinter'
}
console.log(Object.getOwnPropertyDescriptor(person, 'name'))
person.png

2.访问器属性
数据属性不包含数据值,包含一对get和set的核心方法,在读取访问器属性时,就是通过这两个方法进行操作处理的。
访问器属性的四个特性
configurable:表示是否能被delete删除属性且能重新定义该属性。
enumerable:表示能否通过for-in遍历的属性。
get:读取属性时调用的方法,默认值是undefined。
set:写入属性时调用的方法,默认值是undefined。
\color{red}{访问器属性不能直接定义,需要通过Object.defineProperty()来定义。}

let person = {
    name: 'vinter',
    _age: 18, //    下划线是常用标记,表示是内部属性,只能通过对象的方法进行读写
    weight: 120
}
Object.defineProperty(person, 'age', {  // 'age'代替'_age'
    get(){
        return this._age
    },
    set(newValue){
        this._age = newValue
        this.weight += 2
    }
})
person.age = 10
console.log(person.weight, person.age) //   122 10
console.log(Object.getOwnPropertyDescriptor(person, 'age'))
访问器属性.png

从图中可以看到访问器属性的configurable和enumerable两个属性的默认值都是false,如果后面要对该访问器属性进行delete删除时,将configurable转化成true即可。

console.log(Object.getOwnPropertyDescriptors(person))
person对象.png

从图可以看出该对象具有四个属性,\color{red}{ \_age是数据属性,通过它生成了一个age访问器属性。因为访问器属性不能直接定义,所以通过\_age数据属性生成了。}

4. Object的四个相关属性

(defineProperty、defineProperties、getOwnPropertyDescriptor、getOwnPropertyDescriptors)
这四个属性是分为两对:defineProperty vs getOwnPropertyDescriptor、defineProperties vs getOwnPropertyDescriptors。
意思为属性设置和属性的获取解析,第一对上面讲过了,这里就大概说一下第二对的意思,也就是支持设置对个属性,获取多个属性的意思。
Object.defineProperties()

Object.defineProperties(obj, props)
var obj = new Object();
Object.defineProperties(obj, {
    name: {
        value: '张三',
        configurable: false,
        writable: true,
        enumerable: true
    },
    age: {
        value: 18,
        configurable: true
    }
})

console.log(obj.name, obj.age) // 张三, 18

Object.getOwnPropertyDescriptors()
打印出对象的所有属性

Object.getOwnPropertyDescriptors(obj)

5. Object.entries

Object.entries() 方法返回一个给定对象\color{red}{自身可枚举属性的键值对的二维数组。}

let obj = {
   name: 'vinter',
   age: 18
}

let arr = [2, 3, 4]

let string = 'abc'

console.log(Object.entries(obj))  //    [['name', 'vinter'], ['age', 18]]

console.log(Object.entries(arr))    //  [['0', 2], ['1', 3], ['2', 4]]

console.log(Object.entries(string)) //  [['0', 'a'], ['1', 'b'], ['2', 'c']]

Object转Map
new Map()构造函数接受一个二维数组,而Object.entries()方法生成一个二维数组,所以对象、数组、字数串转化为Map结构变得简单。

obj = {name: 'vinter', age: 18}
new Map(Object.entries(obj))
// Map {'name' => 'vinter', 'age' => 18}

6. Object.freeze,Object.preventExtension,Object.seal

正常对象的数据属性都可以被\color{red}{增、删、改、查。}但是通过以下方法,改变了数据属性的四大特性。

  • Object.freeze():冻结对象
    【增、删、改、查】 —— Object.freeze() ==> 【-、-、-、查】
  • Object.perventExtension(): 不可扩展对象
    【增、删、改、查】 —— Object.perventExtension() ==> 【-、删、改、查】
  • Object.seal(): 密封对象
    【增、删、改、查】 —— Object.seal() ==> 【-、-、改、查】

相对应的检测方法,返回Boolean。

  • Object.isFrozen()
  • Object.isExtensible()
  • Object.isSealed()

举例
Object.freeze()方法可冻结对象,冻结后,对象属性不能删除,修改以及添加,只能for...in读取。

obj = {
  name: 'vinter',
  age: 18
}

Object.freeze(obj)

console.log(Object.getOwnPropertyDescriptors(obj))
freeze.png

7. Object.is

该对象方法和==与===运算符相似,但是有明显区别。
Object.is与==比较
== 会将两边的操作数进行隐式转化,之后再进行比较,但是Object.is就不会进行转化。

'' == false  // true
'1' == 1  //  true

Object.is与===比较
=== NaN和NaN不等,-0与+0相等,但是Object.is就认为NaN和NaN是相等,而-0和+0是不相等的。
所以总的来说这两个的相似程度比== 运算符更相近。

8.Object.keys,Object.values

Object.keys()返回一个\color{red}{所有可枚举属性}名称(键)的数组

let arr = [2, 3, 4]
let str = 'abc'

console(Object.keys(arr)) //  ['0', '1', '2']
console.log(Object.str(str)) // ['0', '1', '2']
//  因为JSON对象的特性,所以返回都会是字符串的数组

Object.values()返回可枚举属性值得数组

var obj = { foo: 'bar', baz: 42 }
let str = 'abc'
console.log(Object.values(obj)) //  ['bar', 42]
console.log(Object.values(str)) //  ['a', 'b', 'c']

9.Object.setPrototypeOf

Object.setPrototypeOf(obj, prototype)
为对象obj设置新的原型对象。

注意
如果对象的[[Prototype]]被修改成不可扩展(通过 Object.isExtensible()查看),就会抛出 TypeError异常。如果prototype参数不是一个对象或者null(例如,数字,字符串,boolean,或者 undefined),则什么都不做。否则,该方法将obj[[Prototype]]修改为新的值。

var obj = { foo: 'bar', baz: 42 }
let prototypeC = {name: 'vinter'}

Object.setPrototypeOf(obj, prototypeC)

console.log(obj)
setProtopertyOf.png

下篇文章JS 对象(Object)的深入解析—原型属性

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容