菜菜: “老大,那个, Object.defineProperty 是什么鬼?”

假设我们有个对象 user ; 我们要给它增加一个属性 name , 我们会这么做

1
2
3
var user = {};
user.name="狂奔的蜗牛";
console.log(user);//{name: "狂奔的蜗牛"}

如果想要增加一个sayHi方法叻?

1
2
user.sayHi=function () { console.log("Hi !") };
console.log(user);//{name: "狂奔的蜗牛", sayHi: ƒn}

Object.defineProperty 就是做这个的

那么Object.defineProperty 怎么用?

Object.defineProperty 需要三个参数(object , propName , descriptor)

1 object 对象 => 给谁加
2 propName 属性名 => 要加的属性的名字 【类型:String】
3 descriptor 属性描述 => 加的这个属性有什么样的特性【类型:Object】

那么descriptor这个是个对象 ,他有那些属性呢 ? 别着急我们一个一个说;

既然可以给一个对象增加属性,那么我们用它来做一下给 user添加 name属性,代码是这样的

1
2
3
4
5
var user = {};
Object.defineProperty(user,"name",{
 value:"狂奔的蜗牛"
})
console.log(user);//{name: "狂奔的蜗牛"}

说明 是的还是那个经典的value属性,他就是设置属性值的。

等等,属性值只能为字符串吗?我们的 number function Object boolean 等呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var user = {};
Object.defineProperty(user,"name",{
 value:"狂奔的蜗牛"
})
Object.defineProperty(user,"isSlow",{
 value:true
})
Object.defineProperty(user,"sayHi",{
 value:function () { console.log("Hi !") }
})
Object.defineProperty(user,"age",{
 value:12
})
Object.defineProperty(user,"birth",{
 value:{
  date:"2018-06-29",
  hour:"15:30"
 }
})
console.log(user);

说明 事实证明任何类型的数据都是可以的哦~

问题又来了,如果 user对象已经有了name属性,我们可以通过Object.defineProperty改变这个值吗?

我们来试试

1
2
3
4
5
6
7
var user = {};
Object.defineProperty(user,"name",{
 value:"狂奔的蜗牛"
})
console.log(user);
user.name="新=>狂奔的蜗牛"
console.log(user);

咦??为什么我改了没作用勒??

原因:上边说了descriptor有很多属性,除了value属性还有个 writable【顾名思义属性是否可以被重新赋值】接受数据类型为 boolean(默认为false) true => 支持被重新赋值 false=>只读

哦哦,原来如果我没设置writable值的时候就默认只读啊,所以才改不掉

那我们看看,设置为true,是不是就可以改掉了。

1
2
3
4
5
6
7
8
var user = {};
Object.defineProperty(user,"name",{
 value:"狂奔的蜗牛",
 writable:true
})
console.log(user);
user.name="新=>狂奔的蜗牛"
console.log(user);

这个descriptor还有其他的属性吗?enumerable【顾名思义属性是否可以被枚举】接受数据类型为 boolean(默认为false) true => 支持被枚举 false=>不支持

额。。。枚举??什....什么意思?

假设我们想知道这个 user对象有哪些属性我们一般会这么做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var user ={
 name:"狂奔的蜗牛",
 age:25
} ;
 
//es6
var keys=Object.keys(user)
console.log(keys);// ['name','age']
//es5
var keys=[];
for(key in user){
 keys.push(key);
}
console.log(keys);// ['name','age']

如果我们使用 Object.的方式定义属性会发生什么呢?我们来看下输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var user ={
 name:"狂奔的蜗牛",
 age:25
} ;
//定义一个性别 可以被枚举
Object.defineProperty(user,"gender",{
 value:"男",
 enumerable:true
})
 
//定义一个出生日期 不可以被枚举
Object.defineProperty(user,"birth",{
 value:"1956-05-03",
 enumerable:false
})
 
//es6
var keys=Object.keys(user)
console.log(keys);
// ["name", "age", "gender"]
 
console.log(user);
// {name: "狂奔的蜗牛", age: 25, gender: "男", birth: "1956-05-03"}
console.log(user.birth);
// 1956-05-03

说明 很明显,我们定义为 enumerable=falsebirth属性并没有被遍历出来,遍历 => 其实就是枚举(个人理解啦,不喜勿喷哦~)

总结 enumerable 属性取值为 布尔类型 true | false 默认值为 false,为真属性可以被枚举;反之则不能。此设置不影响属性的调用和 查看对象的值。

configurable 是接下来我们要讲的一个属性,这个属性有两个作用:

1 属性是否可以被删除
2 属性的特性在第一次设置之后可否被重新定义特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var user ={
 name:"狂奔的蜗牛",
 age:25
} ;
//定义一个性别 不可以被删除和重新定义特性
Object.defineProperty(user,"gender",{
 value:"男",
 enumerable:true,
 configurable:false
})
 
//删除一下
delete user.gender;
console.log(user);//{name: "狂奔的蜗牛", age: 25, gender: "男"}
 
//重新定义特性
Object.defineProperty(user,"gender",{
 value:"男",
 enumerable:true,
 configurable:true
})
// Uncaught TypeError: Cannot redefine property: gender
//会报错,如下图

设置为 true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var user ={
 name:"狂奔的蜗牛",
 age:25
} ;
//定义一个性别 可以被删除和重新定义特性
Object.defineProperty(user,"gender",{
 value:"男",
 enumerable:true,
 configurable:true
})
 
//删除前
console.log(user);
// {name: "狂奔的蜗牛", age: 25, gender: "男"}
 
//删除一下
delete user.gender;
console.log(user);
// {name: "狂奔的蜗牛", age: 25}
 
//重新定义特性
Object.defineProperty(user,"gender",{
 value:"男",
 enumerable:true,
 configurable:false
})
 
//删除前
console.log(user);
// {name: "狂奔的蜗牛", age: 25, gender: "男"}
//删除一下 删除失败
delete user.gender;
console.log(user);
// {name: "狂奔的蜗牛", age: 25, gender: "男"}

总结 configurable设置为 true 则该属性可以被删除和重新定义特性;反之属性是不可以被删除和重新定义特性的,默认值为false(Ps.除了可以给新定义的属性设置特性,也可以给已有的属性设置特性哈

最后我们来说说,最重要的两个属性 setget(即存取器描述:定义属性如何被存取),这两个属性是做什么用的呢?我们通过代码来看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var user ={
 name:"狂奔的蜗牛"
} ;
var count = 12;
//定义一个age 获取值时返回定义好的变量count
Object.defineProperty(user,"age",{
 get:function(){
  return count;
 }
})
console.log(user.age);//12
 
//如果我每次获取的时候返回count+1呢
var user ={
 name:"狂奔的蜗牛"
} ;
var count = 12;
//定义一个age 获取值时返回定义好的变量count
Object.defineProperty(user,"age",{
 get:function(){
  return count+1;
 }
})
console.log(user.age);//13

接下来我不用解释了吧,你想在获取该属性的时候对值做什么随你咯~

来来来,我们看看 set,不多说上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var user ={
 name:"狂奔的蜗牛"
} ;
var count = 12;
//定义一个age 获取值时返回定义好的变量count
Object.defineProperty(user,"age",{
 get:function(){
  return count;
 },
 set:function(newVal){
  count=newVal;
 }
})
console.log(user.age);//12
user.age=145;
console.log(user.age);//145
console.log(count);//145
 
//等等,如果我想设置的时候是 自动加1呢?我设置145 实际上设置是146
 
var user ={
 name:"狂奔的蜗牛"
} ;
var count = 12;
//定义一个age 获取值时返回定义好的变量count
Object.defineProperty(user,"age",{
 get:function(){
  return count;
 },
 set:function(newVal){
  count=newVal+1;
 }
})
console.log(user.age);//12
user.age=145;
console.log(user.age);//146
console.log(count);//146

说明 注意:当使用了getter或setter方法,不允许使用writable和value这两个属性(如果使用,会直接报错滴)

get 是获取值的时候的方法,类型为 function ,获取值的时候会被调用,不设置时为 undefined

set 是设置值的时候的方法,类型为 function ,设置值的时候会被调用,undefined

get或set不是必须成对出现,任写其一就可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var user ={
 name:"狂奔的蜗牛"
} ;
var count = 12;
//定义一个age 获取值时返回定义好的变量count
Object.defineProperty(user,"age",{
 get:function(){
  console.log("这个人来获取值了!!");
  return count;
 },
 set:function(newVal){
  console.log("这个人来设置值了!!");
  count=newVal+1;
 }
})
console.log(user.age);//12
user.age=145;
console.log(user.age);//146

【完结】

Object.defineProperty方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象

    • value: 设置属性的值
    • writable: 值是否可以重写。true | false
    • enumerable: 目标属性是否可以被枚举。true | false
    • configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false
    • set: 目标属性设置值的方法
    • get:目标属性获取值的方法      

js中Object.defineProperty()方法的解释的更多相关文章

  1. js中Object.defineProperty()和defineProperties()

    在介绍js中Object.defineProperty()和defineProperties()之前,我们了解下js中对象两种属性的类型:数据属性和访问器属性. 数据属性 数据属性包含一个数据的位置, ...

  2. vue2.x版本中Object.defineProperty对象属性监听和关联

    前言 在vue2.x版本官方文档中 深入响应式原理 https://cn.vuejs.org/v2/guide/reactivity.html一文的解释当中,Object.defineProperty ...

  3. Vue el与data的两种写法 && Object.defineProperty方法

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...

  4. Object.defineProperties()和Object.defineProperty()方法

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

  5. jQuery与JS中的map()方法使用

    1.jquery中的map()方法 首先看一个简单的实例: $("p").append( $("input").map(function(){ return $ ...

  6. ES6中Object.assign() 方法

    ES6中Object.assign() 方法 1. 对象合并Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象上.如下代码演示: var targ ...

  7. Object.defineProperty方法 使用

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

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

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 语法EDIT Object.defineProperty(obj, ...

  9. JavaScript Object.defineProperty()方法详解

    Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 语法 Object.defineProperty(obj, prop ...

随机推荐

  1. Meet in the middle算法总结 (附模板及SPOJ ABCDEF、BZOJ4800、POJ 1186、BZOJ 2679 题解)

    目录 Meet in the Middle 总结 1.算法模型 1.1 Meet in the Middle算法的适用范围 1.2Meet in the Middle的基本思想 1.3Meet in ...

  2. luoguP2590 [ZJOI2008]树的统计(树链剖分)

    luogu P2590 [ZJOI2008]树的统计 题目 #include<iostream> #include<cstdlib> #include<cstdio> ...

  3. window下 nginx 80端口被占用

    问题:启动nginx没有反应,查看日志提示 bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in ...

  4. 实例之跑马灯,函数创建、通过ID获取标签及内部的值,字符串的获取与拼接、定时器的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. asp.net 连续打印多份HTML页面,出现漏字

    在IE8上打印的内容用了CSS 样式,连续打印多份导致的 可以通过改变CSS样式或更换浏览器解决

  6. 全栈开发系列学习2——django项目搭建

    项目代码:http://yunpan.cn/cHajgT4HvgHqx (提取码:8350) 配置项目: 1. 首先确保你的机器安装了python和pip,这两种安装比较简单,这里就不说了. 2. 在 ...

  7. DOM IE 兼容性 I

    IE8事件模型和DOM事件模型有何不同?如何处理DOM事件模型与IE8事件模型的兼容性? 1 事件模型不一样 DOM的浏览器兼容性问题:事件模型   3个阶段            01 外向内:捕获 ...

  8. rpm2cpio - 从 RPM 软件包中提取 cpio 归档

    SYNOPSIS rpm2cpio [filename] DESCRIPTION rpm2cpio 将指定的一个 .rpm 文件转换为一个 cpio 文档,输出到标准输出.如果给出了 `-' 参数,那 ...

  9. quotastats - 显示与配额子系统相关的统计信息

    SYNOPSIS(总览) quotastats DESCRIPTION(描述) 该命令显示与配额子系统相关的统计信息.

  10. linux安装jdk环境(多种方式)

    通过tar.gz压缩包安装 此方法适用于绝大部分的linux系统 1.先下载tar.gz的压缩包,这里使用官网下载. 进入: http://www.oracle.com/technetwork/jav ...