关于javascript中defineProperty的学习

语法

Object.defineProperty(obj, prop, descriptor)

参数

obj
要在其上定义属性的对象。
prop
要定义或修改的属性的名称。
descriptor
将被定义或修改的属性描述符。

返回值

被传递给函数的对象。

使用说明:

我们一般给一个对象创建一个新的属性时,大部分采用的都是如下方式:

var obj = {};
obj.key = "Hello"

但是这种创建方式的属性,其值可被修改,可被遍历等等。 如果想创建隐藏属性(使用for in 无法遍历出来)

或者想创建一个只读属性(不可写入),使用这种方式就不可取了。在ES6中,有一个叫做Symbol类型的东西

这个东西可以人为的定义它是否可写,可枚举,可重配置等等,而定义这个Symbol的方法则是Object对象的 defineProperty

这里可以将Symbol理解为带特殊技能的属性。 我们可以为一个对象,使用defineProperty方法来定义一个带红蓝buff的属性

先来说说属性描述符,由名称可知是用来描述一个属性具有什么特点用的,属性描述符分为两类: 数据描述符存取描述符

数据描述符表示一个具有值的属性,该值可能只读,可能可写

存储描述符表示一个具有对数据进行存取操作的属性。

一个属性只能为以上两种类别中的一个,不能同时是两者

下面是一些上面两个描述符可选的键值:

configurable:  是否允许改变描述符,是否允许删除属性,默认false

enumerable:   是否允许被枚举(for in), 默认false

writeable:   是否可写,默认false

value:    设定数据描述符的value值,默认是undefine

get:     设定存储描述符的getter方法,默认undefine

set:     设定存储描述符的setter方法,默认undefine

注意: configurable enumerable 这两个描述键值 是数据描述符 与 存储描述符 共有的

writeable 和 value 是数据描述符独有的, 而set 和 get方法是存储描述符独有的,另外

这些选项不一定是自身的属性,也需要考虑继承,为确保留有默认值,需要冻结之前的

Object.prototype,或者将__proto__属性指向null

说了那么多概念性的东西,下面来实战练习一下吧

任务一: 创建一个带有只读属性的对象

var o = {};

Object.defineProperty(o, "myName", {
   value: "孙悟空",
   writeable: false        //不允许写,只读的
});

document.write(o.myName);        //孙悟空

//尝试改变属性

o.myName = "猪八戒";              //这里不会报错,但是会抛出readonly
document.write(o.myName);        //孙悟空

任务二: 创建一个带有"隐藏"属性的对象

var o = {};

Object.defineProperty(o, "myName", {
   value: "孙悟空",
   enumerable: false                   //不允许被枚举出来
});

//通过普通方式创建其他属性
o.myAge = 33;
o.myAddress = "China";

//枚举对象所有变量
for(var i in o){
    document.write(i +":"+ o[i] + "<br>");
}

//输出结果:
//myAge: 33
//myAddress: China

//虽然无法遍历出来,但是依然是可以访问的
document.write(o.myName);            //孙悟空

任务三:创建一个带有存储描述符的属性对象

var p;              //稍后使用存储描述符对他进行读写操作
var o = {};

Object.defineProperty(o, "b", {   //属性名为b
        get: function(){
             return p;                //取全局变量
        },

        set: function(value){
             p = value;              //写全局变量
        },

        enumerable: true,        //可遍历
        configurable: true         //可修改
});

o.b = 38;             //看起来像是直接赋值,其实是调用了set方法赋值

document.write(p);   //38, 因为get方法读写的对象是全局变量
    

存储描述符,给人感觉像是对 对象的属性进行读写操作,但其实背后可能是对其他变量的读写

操作,因为可以人为的定义读写操作执行的函数 set/get ,所以我们就可以实现读写时实现自己

想要的功能,比如数据类型判断等等,如果对存储描述符还是不太理解,可以看看下面两段代码

实现一个自存档的属性

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 }]

第二段

var pattern = {
    get: function () {
        return ‘I alway return this string,whatever you have assigned‘;
    },
    set: function () {
        this.myname = ‘this is my name string‘;
    }
};

function TestDefineSetAndGet() {
    Object.defineProperty(this, ‘myproperty‘, pattern);
}

var instance = new TestDefineSetAndGet();
instance.myproperty = ‘test‘;

// ‘I alway return this string,whatever you have assigned‘
console.log(instance.myproperty);
// ‘this is my name string‘
console.log(instance.myname);

对于configurable的效果,大家可能还有疑问,可以阅读下面这段代码,自己动手试试

var o = {};
Object.defineProperty(o, "a", { get : function(){return 1;},
                                configurable : false } );

// throws a TypeError
Object.defineProperty(o, "a", {configurable : true});
// throws a TypeError
Object.defineProperty(o, "a", {enumerable : true});
// throws a TypeError (set was undefined previously)
Object.defineProperty(o, "a", {set : function(){}});
// throws a TypeError (even though the new get does exactly the same thing)
Object.defineProperty(o, "a", {get : function(){return 1;}});
// throws a TypeError
Object.defineProperty(o, "a", {value : 12});

console.log(o.a); // logs 1
delete o.a; // Nothing happens
console.log(o.a); // logs 1

原文地址:https://www.cnblogs.com/demonxian3/p/8952873.html

时间: 2024-10-10 19:48:57

关于javascript中defineProperty的学习的相关文章

javascript中的正则表达式学习

一.前言 关于正则表达式自身的语法这里不做过多介绍(详情可参见http://www.php100.com/manual/unze.html),这里仅仅解释javascript中和正则表达式相关的几个方法的使用. 二.javascript中的RegExp对象 在javascript中,有两种方法可以构建正则: 正则表达式字面量 RegExp构造器 RegExp对象有以下属性: global:如果标识g,则为true ignoreCase:如果标识i被使用,则为true lastIndex:下一次e

JavaScript中 Promise的学习以及使用

今天一个哥们发过来一段js代码,没看懂,就顺便学习了一下,代码如下 Promise.resolve('zhangkai').then(value => {console.log(value)}) 经过搜索,才知道是Promise的应用,于是就做一下笔记,整理一下,以及项目中可以派上的用场. 什么是Promise对象 Promise对象是CommonJS工作组为异步编程提供的统一接口,是ECMAScript6中提供了对Promise的原生支持,Promise就是在未来发生的事情,使用Promise

JavaScript中NODE操作学习总结

Node: 1.在 HTML DOM (文档对象模型)中,每个部分都是节点:    文档本身是文档节点     所有 HTML 元素是元素节点     所有 HTML 属性是属性节点     HTML 元素内的文本是文本节点     注释是注释节点  2.节点属性:    element.childNodes 返回元素子节点的 NodeList     element.className 设置或返回元素的 class 属性     element.firstChild 返回元素的首个子节点   

javascript中的事件学习总结

一.实例: 一段用js实现的固定边栏滚动特效代码(跨浏览器使用): 二.总结: 由于事件处理在不同浏览器之间存在差异(主要是要考虑ie8及以下浏览器的兼容性),所以在使用处理事件的方法之前,先要判断当前使用的浏览器是否含有该方法(这种方法也叫平稳退化,防止我们写的页面因为在某些不兼容我们在页面中写的js,而不能正常显示我们写的页面的情况). 1.两种事件处理的方法:addEventListener()和attachEvent(): addEventListener('event',evenfun

Javascript 中的arguments 学习

arguments是当前正在执行的function的一个参数,它保存了函数当前调用的参数. 使用方法:function.arguments[i]. 其中function.是可选项,是当前正在执行的function的名称. arguments不能够创建,是函数自身的参数,只有当函数开始执行是才能使用. 虽然arguments的使用方法,很像数组,但是它并不是数组. 下面,用例子来进行演示: function argumentsTest (a,b) { alert(typeof arguments)

[JavaScript]JavaScript中的函数(1)

关于JavaScript中函数的学习: MDN 阮一峰老师的教程 关于函数的定义: 阮一峰老师:函数是一段可以反复调用的代码块.函数还能接受输入的参数,不同的参数会返回不同的值. MDN:Function 构造函数 创建一个新的Function对象. 在 JavaScript 中, 每个函数实际上都是一个Function对象. 函数的声明方式和name 函数的声明方式有目前来说有5种,每一个函数都有他的一个name属性(包括匿名函数),要注意. 具名函数 function fn(x,y) { c

好程序员web前端学习路线之在JavaScript中使用getters和setter

好程序员web前端学习路线之在JavaScript中使用getters和setter,大多数面向对象的编程语言都存在getter和setter,包括JavaScript.它们是代码构造,可帮助开发人员以安全的方式访问对象的属性.使用getter,您可以从外部代码访问("获取")属性的值,而setter允许您更改("设置")它们的值.我们将向您展示如何在JavaScript中创建getter和setter. JavaScript对象可以具有多个属性和存储的静态数据和动

如何理解并学习javascript中的面向对象(OOP) [转]

如果你想让你的javascript代码变得更加优美,性能更加卓越.或者,你想像jQuery的作者一样,写出属于自己优秀的类库(哪怕是基于 jquery的插件).那么,你请务必要学习javascript面向对象,否则你无法更灵活的使用javascript这门语言. 什么事闭包?到底什么是原型?(知道闭包和原型的,就算得上是javascript的高手了.但真正能够理解,并且灵活运用的人并不多)到底该如何学习javascript中的面向对象呢?在javascript这么语言正如日中天,相信不少人正在为

学习JavaScript中的异步Generator

本文和大家分享的主要是javascript中异步Generator相关内容,一起来看看吧,希望对大家学习javascript 有所帮助. 异步的generators和异步iteration已经到来 ! 这是错误的, 它们现在还在 阶段 3 ,这表示他们很有可能在JavaScript未来的一个版本中发布. 在他们发布之前,你可以通过 Babel 来在你的项目中使用还在阶段3的建议内容. 网站基本上还是一些分散运行的应用,因为任何在语言上的修改都会造成永久的影响,所以所有的未来的版本都需要向后兼容.