Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >js对象属性

js对象属性

作者头像
RobinsonZhang
发布于 2018-11-07 06:49:23
发布于 2018-11-07 06:49:23
15.7K00
代码可运行
举报
运行总次数:0
代码可运行

前言

相信对于对象属性大家都或多或少的知道一些,那么本文从属性说开去,看看大家对属性的了解是否有遗漏的部分。

属性的定义与使用

也许你觉得定义属性很简单啊,我直接.prop = xxx,就可以定义个对象了啊,从未深入了解,这在大多数情况下没有任何问题。但在某些情况下就不够用了。

我们知道的使用方式是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let param = {
id:'',
number:13
}
param.query = 'sfwefw'
param['say']= () => {
console.log(111)
}
console.log(param.number)

那么我们先追本溯源看下对象定义属性官方的玩法吧。 官方对属性分为两种,一种是数据属性,另一种访问器属性。(这些属性值为了区别于我们理解的普通属性,我们用两对括号体现)

简单表格统计下他们的特征

属性

内容

特征

数据属性

configurable,enumerable,writable,value

其中123均为布尔型,默认为true,分别代表可删除、可枚举、可修改,第四个为true

访问器属性

configurable,enumerable,getter,setter

后面两个是非必须的

虽然似乎说的很明白,但还是一脸懵逼,感觉对自己没什么影响啊。那么干货来了,我通过几个经典的高频点来延伸的帮助大家理解这部分。

for in 循环遍历的属性

作为经常使用对象的我们,想必对这个语法并不陌生,虽然我们一般情况下很少直接这样用,因为更多业务场景下是属性的精准使用,不会通过循环的方式,原因有以下几个方面。当然你可以跳过这部分。

1 如果默认使用属性循环来展示数据,有很多不必要展示的数据都要过滤筛选掉,比较低效麻烦 2 属性的循环访问不一定符合我们需要展示的顺序,这点才是致命的,导致我们在业务需要的时候更多的时候是固定顺序固定访问对象属性 3 如果对对象属性期望按照顺序,会大大的增加数据改造的成本,增加不可复用的解耦成本

回到正文,重头戏来了,作为常识需要了解到两点。

第一点,for in循环可以访问到对象具有的所有可枚举属性; 第二点 对象具有的属性可能是多来源的,可能是自己新建的,可能是构造函数新建的,可能是来源于构造函数的继承;可能是来源于原型,可能是来源于原型式的继承。其中我们可以通过hasOwnProperty来判断这个属性是否是自有属性(构造函数来的是判断不出的)。

构造函数得到的属性以及基本属性赋值
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//正常的构造函数以及对象属性赋值,call .apply构造函数继承方式的属性都可以正常获取,并且属于对象自有属性
let Animal = function (){
  this.bigtype = 'animal'
}
let Person = function () {
  this.name = '人类' 
  this.sex = '男女'
  Animal.call(this)
} 
let zhangsan = new Person('zhangsan','male')
zhangsan.type = 'animal'
for(let p in zhangsan){
 console.log(zhangsan.hasOwnProperty(p),`${p}:${zhangsan[p]}`)
}

特别说明:为什么构造函数之后对象的属性都是自有属性呢? 这个要和new关键字有关了,其关键的四个步骤是创建新的对象,然后构造函数的作用域指向新对象(this指向新对象),执行构造函数中的代码,返回新对象。所以自然通过this赋值的都是新对象的属性了。

原型链方法赋值以及原型链继承方式

无论是通过原型修改属性还是原型链继承的其他原型,其均不属于对象自己,均是向上追溯的原型对象的,所以hasOwnProperty均为false.

需要注意的是 :1 如果你需要继承其他原型,又需要修改原型的某个值,要先继承在修改值,不然你修改的值就丢失了。2 继承原型要在实例化对象之前,写在调用之前是无效的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let Animal = function (){
  this.bigtype = 'animal'
}
let Person = function () {
  this.name = '人类' 
  this.sex = '男女'
  // Animal.call(this)
} 
Person.prototype = new Animal()
Person.prototype.belong = 'zhang'
let zhangsan = new Person('zhangsan','male')
for(let p in zhangsan){
 console.log(zhangsan.hasOwnProperty(p),`${p}:${zhangsan[p]}`)
}
参考代码

还什么方法可以拿到属性

没错,我们一般情况下使用for,in循环获取属性,但有些属性我们也希望得到。通过上面的for in的例子,你可以通过for in +hasOwnProperty 的方式得到对象可枚举非原型属性以及可枚举原型属性。那么还有其他方法么?肯定有的。下面进行表格说明。

方法

内容

备注

for in

可枚举,自身以及继承属性

对象以及继承,可枚举,不含 Symbol 属性

Object.keys(obj)

返回一个数组,包括对象自身的(不含继承的)所有可枚举属性键名

对象自身可枚举,不含 Symbol 属性

Object.getOwnPropertyNames(obj)

返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名

对象自身,包括不可枚举属性

Object.getOwnPropertySymbols(obj)

返回一个数组,包含对象自身的所有 Symbol 属性的键名

对象自身,symbol

Reflect.ownKeys(obj)

返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

对象自身,全部属性

属性中的this是什么

来源

指向

对象

对象自身

构造函数

返回新对象

原型

原型

纯函数调用

外部环境全局,浏览器或者node

访问器get,set使用

一般我们也用不到这个,但vue的数据双向绑定就是基于这个实现的,其在data属性中定义的数据,全部对其属性的属性定义中追加了虚拟dom的事件,所以能够实现双向绑定。也正因为这个属性的兼容问题,导致了vue不支持ie低版本哦。

参考源码vue框架使用get,set源码地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if (process.env.NODE_ENV !== 'production' && customSetter) {
        customSetter()
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = !shallow && observe(newVal)
      dep.notify()
    }
  })
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
vue 响应式原理
简单点讲 vue 的响应式是通过 Object.defineProperty 和 观察者模式来实现的。 vue 初始化的时候 watcher 构造函数通过 Object.defineProperty 方法对 data 属性进行递归遍历,设置 get、set,初始化编译的时候会触发 getter 函数,进行依赖收集,将观察者 watcher 添加到目标对象 dep 中。改变数据的时候会触发 set, 执行 notify 方法,调用 dep 中 watcher 对象的 update 方法,update 方法将 watcher 添加到 watcher 队列中, 通过调用 nextTick 异步执行,触发更新。
大当家
2020/04/01
5790
VUE源码解读之响应式系统及Watcher的调度实现
鉴于目前 vue3 还没有正式发布,而且 vue2 里面的一些实现思想还是很有参考价值的,于是这篇原理性讲解还是 vue2 的,希望对你有启发~
winty
2020/04/01
9490
vue源码分析之defineReactive方法中为什么有两种dep在收集依赖?
了解vue响应式原理对童鞋,想必对defineReactive方法有印象,这是vue响应式的核心方法。在这个方法,给obj的每个key对应的都new了一个dep,这个dep保存在defineReactive闭包中。这个dep的作用非常明显,收集当前watcher,以便在触发obj属性set方法的时候通知watcher更新。
玖柒的小窝
2021/10/05
1.8K1
Vue 核心之数据劫持
Angular、Regular、Vue、React等等可以实现数据绑定,再也不需要手动进行DOM操作了,它们实现的原理也基本上是脏检查或数据劫持。 本文就以Vue框架出发,学习Object.defineProperty来实现数据劫持。
前端小tips
2021/11/25
3510
Vue 核心之数据劫持
Vue响应式依赖收集原理分析-vue高级必备
在 Vue 的初始化阶段,_init 方法执行的时候,会执行 initState(vm) ,它的定义在 src/core/instance/state.js 中。在初始化 data 和 props option 时我们注意 initProps 和 initData 方法中都调用了 observe 方法。通过 observe (value),就可以将数据变成响应式。
yyds2026
2022/10/26
5770
简单通俗的理解Vue3.0中的Proxy
什么是代理呢,可以理解为在对象之前设置一个“拦截”,当该对象被访问的时候,都必须经过这层拦截。意味着你可以在这层拦截中进行各种操作。比如你可以在这层拦截中对原对象进行处理,返回你想返回的数据结构。
木子星兮
2020/03/12
1.5K0
简单通俗的理解Vue3.0中的Proxy
每日一题之Vue数据劫持原理是什么?
定义: 数据劫持,指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。
bb_xiaxia1998
2022/10/06
5160
vue源码分析-响应式系统工作原理
上一章,我们讲到了Vue初始化做的一些操作,那么我们这一章来讲一个Vue核心概念响应式系统。
yyzzabc123
2022/10/19
4740
vue源码分析-响应式系统工作原理_2023-03-01
上一章,我们讲到了Vue初始化做的一些操作,那么我们这一章来讲一个Vue核心概念响应式系统。
用户10377014
2023/03/01
4540
《你不知道的JavaScript》:js对象的属性特性和枚举深入
可以看到,检测属性的结果打印为4个属性数据描述符:value(属性值)、writable(可写)、enumerable(可枚举)、configurable(可配置)。
前端_AWhile
2019/08/29
1.1K0
Vue2剥丝抽茧-响应式系统之数组
接 Vue2剥丝抽茧-响应式系统、Vue2剥丝抽茧-响应式系统之分支切换,响应式系统之嵌套 、响应式系统之深度响应 还没有看过的同学需要看一下。
windliang
2022/08/20
1720
Vue2剥丝抽茧-响应式系统之数组
《你不知道的js(上卷)》笔记2(this和对象原型)
this关键字是javascript中最复杂的机制之一。它是一个很特别的关键字,被自动定义在 所有函数的作用域中。
陨石坠灭
2020/01/21
7030
2. 「vue@2.6.11 源码分析」数据驱动视图(响应式)
vue 最核心的卖点是数据驱动和组件。浏览器原生提供的交互是通过dom api来修改dom元素,由于浏览器兼容性问题后面的框架如jquery对原生的api进行了一层的封装以屏蔽浏览器的差异性,但并未作出实质的改变。想想这个过程,通常是数据发生变化,js根据变化的情况进行判断而后操作dom。dom变动的本质实际根本上实际是由数据驱动,我在第一家公司数字政通(egova)首次接触了的此类框架knockout。
tinyant
2023/02/24
5380
2. 「vue@2.6.11 源码分析」数据驱动视图(响应式)
​vue源码分析前置知识必备
最近利用空闲时间又翻看了一遍Vue的源码,只不过这次不同的是看了Flow版本的源码。说来惭愧,最早看的第一遍时对Flow不了解,因此阅读的是打包之后的vue文件,大家可以想象这过程的痛苦,没有类型的支持,看代码时摸索了很长时间,所以我们这次对Vue源码的剖析是Flow版本的源码,也就是从Github上下载下来的源码中src目录下的代码。不过,在分析之前,我想先说说阅读Vue源码所需要的一些知识点,掌握这些知识点之后,相信再阅读源码会较为轻松。
前端老鸟
2019/07/29
6330
请你挑战一下这几道nextTick面试题
Vue大家再熟悉不过了,Vue的this.$nextTick大家也再熟悉不过了,今天我们就来看看自创的nextTick相关的几道面试题,看看你是否真正理解Vue的nextTick。
kai666666
2024/07/11
1170
重学前端(二)-你真的了解你JS的对象吗?
ECMAScript标准+ webAPI 那么我们今天要一起学习的就是ECMASciript中的-Object,他实际上是一个es的语言标准
用户7413032
2020/06/11
1.1K0
重学前端(二)-你真的了解你JS的对象吗?
面向对象的程序设计
ECMA-262把对象定义为:”无序属性的集合,其属性可以包含基本值、对象或者函数。”
奋飛
2019/08/15
4300
JS与ES6高级编程学习笔记(三)——JavaScript面向对象编程
面向对象程序编程(Object-oriented programming,缩写:OOP)是用抽象方式构建基于现实世界模型的一种编程模式,JavaScript是一种基于对象(object-based)的语言,支持面向对象编程与函数式编程,但JavaScript的面向对象与其它的面向对象语言有较大差异,ECMAScript中没有类的概念,所以对象也有所不一样。
张果
2022/06/06
7420
JS与ES6高级编程学习笔记(三)——JavaScript面向对象编程
JS 原生面经从初级到高级【近1.5W字】
1.函数声明有预解析,而且函数声明的优先级高于变量; 2.使用Function构造函数定义函数的方式是一个函数表达式,这种方式会导致解析两次代码,影响性能。第一次解析常规的JavaScript代码,第二次解析传入构造函数的字符串
火狼1
2019/10/23
1.1K0
JS 原生面经从初级到高级【近1.5W字】
JavaScript 高级程序设计(第 4 版)- 对象、类与面向对象编程
通过字面量来重写原型时,Person.prototype被设置为等于一个通过对象字面量创建的新对象,此时Person.prototype的constructor属性就不指向Person了
Cellinlab
2023/05/17
6380
JavaScript 高级程序设计(第 4 版)- 对象、类与面向对象编程
推荐阅读
相关推荐
vue 响应式原理
更多 >
LV.1
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验