Object.defineProperty()的学习了解

2023-05-16

背景

最近在总结vue系列的时候是看到响应原理的时候,看到一个新的知识点也就是我们的标题Object.defineProperty()的时候,好了话不多说,我们来看看这个是怎么使用的

开始

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。 --- MDN

上面这句话是MDN上写的,当你看到这句话的时候有什么感觉吗?没有?其实我看到这句话的时候确实也没什么感觉,那怎么办我们在看一边,哦发现了,cao,添加属性什么时候要怎么麻烦了写一个这么长的代码啊,我以前都是这样写的

对象添加属性方法

1.构造法

var obj = new Object;  //obj = {}
obj.name = "张三";  //添加描述
obj.say = function(){};  //添加行为

2.字面量法

var obj = {
    name : "张三",
    say  : function(){}
}

 

语法

我们来看下object.defineProperty的语法从而去了解他和我们以前的写法有什么不一样

作用

一:针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写(不可以修改);是否可以被for..inObject.keys()遍历(不会被被枚举遍历),用object.defineProperty写出来的属性,默认值是不可修改,和不会被遍历出来的,(后面会讲)

二:其实object.definePorperty的存取器描述有点绑定事件的感觉(后面会写)

参数

Object.defineProperty(obj, prop, descriptor)
obj :目标对象
prop :需要定义或修改的属性
descriptor :需要定义或修改的属性描述符

返回值

返回的是一个对象,就是我们修改后的obj对象

属性描述符(第三个参数)

给对象的属性添加特性描述,目前提供两种形式:数据描述存取器描述。

数据描述符和存取描述符均共同具有以下可选键(属性)值:

configurable

当且仅当该属性的 configurable 为 true 时,该属性描述符(就是像configurable,enumerable之类的描述符)才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false

//-----------------测试目标属性是否能被删除------------------------
var obj = {}
//第一种情况:configurable设置为false,不能被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //hello

//第二种情况:configurable设置为true,可以被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //undefined

//-----------------测试是否可以再次修改特性------------------------
var obj = {}
//第一种情况:configurable设置为false,不能再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});

//重新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey

//第二种情况:configurable设置为true,可以再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});

//重新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //hello

enumerable

当且仅当该属性的enumerabletrue时,该属性才能够出现在对象的枚举属性中。默认为 false

这也说明了为什么用object.defineProperty()的时候默认是不可修改,和不会被枚举出来的了

那么我们说明了共同点我们就来分别来说明他们直接的写法

数据描述符

(configurable,configurable)

value

该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。当value没有定义的时候,值为undefined, 和一般情况下一样的

writable

当且仅当该属性的writabletrue时,value才能被赋值运算符改变,重新重写成功,默认为 false

默认情况下在数据描述符写法下value的值是不可以随便改变的,

var obj = {}
//第一种情况:writable设置为false,不能重写。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //hello

//第二种情况:writable设置为true,可以重写
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //change value

存储器描述符

(configurable,configurable)

get

一个给属性提供 getter(取) 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象

默认为 undefined

set

一个给属性提供 setter (改,设置)的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的属性值(就是我们定义字符属性值修改的值)。

默认为 undefined

注意:当使用了getter或setter方法,不允许使用writable和value这两个属性,二种不同的用法,一般情况下第二种用的多

var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //当获取值的时候触发的函数
        return initValue;    
    },
    set:function (value){
        //当设置值的时候触发的函数,设置的新值通过参数value拿到,这里value的值就是我们更改的值
        initValue = value;
    }
});
//获取值
console.log( obj.newKey );  //hello

//设置值
obj.newKey = 'change value';

console.log( obj.newKey ); //change value

注意:get或set不是必须成对出现,任写其一就可以。如果不设置方法,则get和set的默认值为undefined

看一个set和get使用的例子

下面的例子展示了如何实现一个自存档对象。 当设置temperature 属性时,archive 数组会获取日志条目。

function Archiver() {
  var temperature = null;
  var archive = [];

  Object.defineProperty(this, 'temperature', {
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
      temperature = value;
      archive.push({ val: temperature });
    }
  });

  this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]

如果你这个看懂了那就恭喜你了,应该是会了

object.defineproperty与继承之间的问题

如果访问者的属性是被继承的,它的 get 和set 方法会在子对象的属性被访问或者修改时被调用。如果这些方法用一个变量存值,该值会被所有对象共享。

function myclass() {
}

var value;
Object.defineProperty(myclass.prototype, "x", {
  get() {
    return value;
  },
  set(x) {
    value = x;
  }
});

var a = new myclass();
var b = new myclass();
a.x = 1;
console.log(b.x); // 1

 

那么如何结局上面的问题:在继承的对象中添加的属性值会被继承

在解决问题的时候我们先分析问题:这里的访问者就是a和b他们的x属性就是继承过来的,那么a或b中的x的属性值发生改变的时候他们继承的get方法和set方法会触发,所以有引发了下一个问题(get或set函数中的this的指向),那么这里的this的指向就是他们的访问者,是访问值触发的get或set函数

那么解决问题的方法就是,当触发set的时候给自己对于的访问者添加属于自己的属性值。

function myclass() {
}

Object.defineProperty(myclass.prototype, "x", {
  get() {
    return this.stored_x;
  },
  set(x) {
    this.stored_x = x;
  }
});

var a = new myclass();
var b = new myclass();
a.x = 1;
console.log(b.x); // undefined

注意:一般情况下在原型(prototype)中建立的属性值,与new出来的实例中的属性值是没有关系的,直接修改实例上的方法是不会影响原型是的方法的

------一般情况下------

 function myclass() {}
 myclass.prototype.b = 10;
 var b = new myclass();
 console.log(b.b); // 10
 b.b =2;
 console.log(b.b); // 2 这里发生了改变
 console.log(b.prototype.b) //10  

------object.defineProperty-------
function myclass() {
}
Object.defineProperty(myclass.prototype, "y", {
  writable: false, // 不管这里是false 还是 true
  value: 1
});

var a = new myclass();
a.y = 2; // Ignored, throws in strict mode
console.log(a.y); // 1 这里没有改变
console.log(myclass.prototype.y); // 1 

好了这里就是这篇快结束了,那么和vue的响应式有什么关系呢?当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 object.defineproperty 把这些属性全部转为 getter/setter.这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化,其实就是model改变后通过object.defineproperty来改变view中的值,来达到单向数据流,而不是双向绑定(vue中不是双向绑定)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Object.defineProperty()的学习了解 的相关文章

  • 定位插件

    写了个等位插件 xff0c 点击nav中的LI xff0c 位移 xff08 与href有视觉效果 xff09 到达相应板块 xff08 这里的类比li中的类中多了个H字母 xff09 的位置 lt li class 61 34 wz 34
  • JQ复习

    一选择器 1 基本选择器 2 层级选择器 3 过滤选择器 first 选取第一个元素 last 选择最后一个元素 not 去除所有与给定选择器匹配的元素 39 input not first 39 even选取索引是偶数的元素 xff0c
  • 第7章艺术编程Ajax的学习

    终于学到Ajax以前一直没接触到一直以为很NB xff0c 对这些内容我基本上是个小白中的小白哎 xff0c 继续加油 Ajax可以做到只更新页面的一下部分 xff0c 其他部分不需要重新加载 下面就是根据书上的内容所写 HTML lt d
  • 函数是否加括号的问题

    lt a onclick 61 34 fun 34 gt lt a gt 这里有括号 document getElementById 34 ID 34 onclick 61 fun 这里不可以有括号 为什么会有这样的不同 首先加上括号是执行
  • this的详细分析加案例

    this对象是在函数运行时候基于函数的执行环境 xff08 上下文 xff09 绑定的 方法调用模式函数调用模式改造器调用模式apply call bind调用模式 1 方法调用模式 函数有所属对象 xff0c 也就是这个函数是myObje
  • 构造函数与原型链和面向对象的学习(一)

    什么是构造函数 构造函数就是一个普通的函数 xff0c 里面可以写任何语句 逻辑语句或DOM操作 xff0c 可以new出新的实例 xff0c 使其实例可以共享构造函数的原型 第一个例子 function Fun this name 61
  • 构造函数与原型链和面向对象的学习(二)

    原型链 proto proto 也就是对象的 prototype 属性 每一个函数都有一个属性叫做prototype 指向一个对象 不是函数就没有这个属性 这个对象叫原型对象 当这个构造函数被new的时候 xff0c 他的每一个实例对象的
  • 构造函数与原型链和面向对象的学习(三)

    小案例 xff08 红绿灯 xff09 下面对面向对象写个小案例 xff08 红绿灯 xff09 上面是原图 用来来实现点击图片 xff0c 红绿灯的颜色改变 xff0c 控制背景图片的定位来改变 点击一下 就是要完成上面的效果 如果只要实
  • js中的预编译和作用域链

    预编译目的 1 定义作用域中的初始化词法环境 xff0c 而词法环境中有定于作用域 xff0c 从而规定了变量的作用域 2 先是在为undefined xff0c 减少运行时报错 形参去实参的区别 1 形参变量只有在被调用时才分配内存单元
  • ffmpeg视频处理神器学习基础笔记

    FFmpeg文档汇总 xff1a https ffmpeg org documentation html FFmpeg filters文档 xff1a https ffmpeg org ffmpeg filters html 视频处理 视频
  • Vue.js动画和过渡

    vue中的过渡与动画 过滤 把需要添加动画效果的DIV放到transition标签 之后就会发生以下3个步骤 自动嗅探目标元素是否应用了 CSS 过渡或动画 xff0c 如果是 xff0c 在恰当的时机添加 删除 CSS 类名 等下要写的6
  • Vue.js使用keyframes动画

    lt DOCTYPE html gt lt html gt lt head gt lt meta charset 61 34 utf 8 34 gt lt title gt Vue中css动画的原理 lt title gt lt scrip
  • Vue.js使用animate.css框架

    1 如何使用animate框架 lt DOCTYPE html gt lt html gt lt head gt lt meta charset 61 34 utf 8 34 gt lt title gt Vue中css动画的原理 lt t
  • vue.js中添加动画

    通过触发事件 xff0c 改变data中的值 xff0c 或者改变点击标签元素上的属性值 lt DOCTYPE html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 6
  • 多个元素和列表的过渡

    多个元素 lt DOCTYPE html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt title gt 多个元素的组件的过渡动
  • flex弹性布局的学习

    布局的传统解决方案是基于盒状模型 xff0c 依赖 display 43 position 43 float 方式来实现 xff0c 灵活性较差 2009年 xff0c W3C提出了一种新的方案 Flex xff0c Flex是Flexib
  • 震惊!Ajax项目中的使用

    啊啊 xff01 实习第一天写了个移动端的分享列表 就在第三天我们的技术大佬亲自教我们如何对接后台 当然用的是我写的移动端的分享列表 虽然这次应用不是很深入 xff0c 但还是比较广泛 用到了Ajax xff0c sui框架 zepto x
  • 关于viewport视口的学习

    简单来说 lt meta name 61 34 viewport 34 content 61 34 width 61 device width initial scale 61 1 0 34 gt content属性值 width 可视区域
  • 淘宝的H5布局

    利用viewport和rem布局实现的淘宝布局 下面先看看em布局的原理 em作为font size的单位时 xff0c 其代表父元素的字体大小 xff0c em作为其他属性单位时 xff0c 代表自身字体大小 MDN em作为字体单位 x
  • css的优先级

    优先级 浏览器通过优先级来判断哪些属性值与一个元素最为相关 xff0c 从而在该元素上应用这些属性值 优先级是基于不同种类选择器组成的匹配规则 优先级是如何计算的 优先级就是分配给指定的 CSS 声明的一个权重 xff0c 它由 匹配的选择

随机推荐

  • Django设置分享到微信好友和朋友圈时的标题、摘要、链接和图片

    主要参考官方文档 1 前端分享给好友和朋友圈的js代码 share html lt DOCTYPE html gt lt html lang en gt lt head gt lt meta charset UTF 8 gt lt meta
  • 孙其功陪你学之——如何将shell命令的返回值赋值给应用程序的变量

    如何将shell命令的返回值赋值给应用程序的变量 博主最近做了个路由器的项目 xff0c 需要得到路由器现在网络状态和参数 xff0c 使用UCI get 获得 xff0c 但是使用了system xff08 UCI get xff09 之
  • shell编程2条件语句

    文章目录 shell编程之条件语句1 条件测试1 1 返回值1 2 test 2 文件测试3 整数值比较4 逻辑测试5 if语句5 1 单分支 if 语句5 2 双分支 if 语句5 3 多分支 if 语句 6 case 语句7 实验7 1
  • html和css的hack的学习

    在整理基础的时候总结 html和css的hack的学习 hack是什么 xff1f 就是针对不同的浏览器写不同的css样式让各浏览器能达到一致的渲染效果 xff0c hack分为HTML和CSS HTML hack lt if lte IE
  • 数组的迭代与归并的方法

    迭代的作用 xff1a 减少代码量 xff1a 例如因为map xff0c filter方法会自动生产数组不用自己在for创建 xff0c 有利于性能优化 xff1b 和无需知道对象的长度 补充19 6 11 xff1a 迭代的方法是表达式
  • js数组的常见属性和方法

    属性 strong length strong 是Array的实例属性 返回或设置一个数组中的元素个数 该值是一个无符号 32 bit 整数 xff0c 并且总是大于数组最高项的下标 xff0c 不只是可读 Array prototype
  • js闭包的作用和应用的学习

    什么是闭包 一个函数和对其周围状态 xff08 lexical environment xff0c 词法环境 xff09 的引用捆绑在一起 xff08 或者说函数被引用包围 xff09 xff0c 这样的组合就是闭包 xff08 closu
  • css面试题布局

    不试试怎么知道自己行不行 昨天加了张鑫旭的微信 xff0c 我草贼开心 xff0c 发现他星期六会直播 xff0c 一下就是我看直播学到的一些总结 那么是什么呢 xff1f 其实就是一个简单的左右排版 xff0c 在张老师的讲了4种不是很好
  • 获取css的方法区别

    不试试怎么知道自己不可以 xff1f 对吧 首先我们要知道css在HTML中有多少总方法 xff1f 呵呵大家都知道的 行内 xff1a 顾名思义就是和标签在同一行 lt div class 61 34 text 34 style 61 3
  • 关于offsetLeft和offsetTop的兼容性问题

    不试一下怎么知道自己不可以 xff1f 首先我们要看下offsetLeft和offsetTop他们两的API的作用 xff1b 元素相对于offsetParent的左边距和上边距 xff08 为什么没有bottom xff0c right呢
  • js深度拷贝和浅度拷贝的深入理解

    首先我们来说说什么是拷贝 xff1a 就是复制的同时加上了传值 然后问题就来了什么是有深度的什么是浅度的 xff0c 在想要了解我们这个问题之前我们先来了解一下下面的一个知识点 基本类型传递 xff0c 引用类型传递 首先我们来看下基本类型
  • npm的基本使用

    npm的下载 npm的下载其实就是把node js 百度下node官网 下载好了那么npm就附带下载好了 检查是否下载好 window 43 r 后输入cmd打开终端 xff0c 在终端中输入node v xff1b npm v 他们会输出
  • 从 (a==1&&a==2&&a==3) 成立中看javascript的隐式类型转换

    几天上班看到一个题目就是 if a 61 61 1 amp amp a 61 61 2 amp amp a 61 61 3 console log 34 a等于什么才会输出这一句话呢 xff1f 34 当a为什么的时候输出 xff1a a等
  • Bootstrap实用功能总结

    导航栏 xff1a navbar 导航栏容器可以包含以下几个常用组成 xff1a 1 品牌LOGO xff08 navbar brand xff09 2 导航菜单 xff08 navbar nav xff09 3 导航文本 xff08 na
  • 微信小程序的AJAX初次体验

    GET请求 微信小程序用GET传送数据 微信小程序通过 wx request发送ajax请求 wx request url app globalData pubSiteUrl 43 39 user information get infor
  • vue总结系列 ------ 组件之间的传值

    原因 半年前开始学Vue学到了今天 xff0c 也没有机会好好整理一下自己的知识点 xff0c 因为上公司的项目不是依赖于Vue xff0c 还是在用JQ 和文件之间来传递代码 xff0c 所以其实在对vue的学习成面上来讲对我的帮助并不大
  • vue总结系列 --- 插槽slot

    前因 这个是我这个系列的第二篇 这一篇文章我也修改过三次 xff08 2019 9 10 xff09 我是想以vue官方文档为基础 xff0c 来进行理解 xff0c 有人说有官方文档 xff0c 还要写自己的文章干嘛 xff0c 我的用意
  • vue总结系列 --- 生命周期

    前言 在总结其他的时候发现还是应该先复习vue的生命周期 xff0c 所以就先把生命周期先复习完了 经过一系列的视频 xff0c 文档我把我的总结写一下生命周期分为3个阶段 xff1a 创建 xff0c 更新 xff0c 和销毁 我们看图说
  • vue总结系列 ---- 响应式原理

    检测变化 vue是数据驱动的视图框架DOM是通过数据映射的 xff0c 只有数据改变 xff0c DOM才改变 那么数据是怎么来的呢 xff1f 1 来自父元素的属性 xff08 prop xff09 2 来自组件的自身状态 xff08 d
  • Object.defineProperty()的学习了解

    背景 最近在总结vue系列的时候是看到响应原理的时候 看到一个新的知识点也就是我们的标题Object defineProperty 的时候 xff0c 好了话不多说 xff0c 我们来看看这个是怎么使用的 开始 strong Object