JS apply的巧妙用法以及扩展到Object.defineProperty的使用
Math.max 实现得到数组中最大的一项
- var array = [1,2,3,4,5];
- var max = Math.max.apply(null, array);
- console.log(max); //
调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,只需要用这个方法帮助运算,得到返回的结果就行,所以直接传递了一个null过去。
Math.min 实现得到数组中最小的一项
- var array = [1,2,3,4,5];
- var min= Math.min.apply(null, array);
- console.log(min); // 1
在原生对象上面添加max与min方法
那就会需要用到原生对象方法Object.defineProperty()
,会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象
- Object.defineProperty(Array.prototype, 'max', {
- writable: false,
- enumerable: false,
- configurable: true,
- value: function () {
- return Math.max.apply(null, this);
- }
- });
- Object.defineProperty(Array.prototype, 'min', {
- writable: false,
- enumerable: false,
- configurable: true,
- value: function () {
- return Math.min.apply(null, this);
- }
- });
直接在数组上调用即可:
- var arr = [54,545,2165,545,56];
- console.log(arr.max());
- console.log(arr.min());
上面讲到了Object.defineProperty的方法,下面我们来理解下。
Object.defineProperty的使用
对象是由多个名/值对组成的无序的集合。对象中每个属性对应任意类型的值。定义对象可以使用构造函数或字面量的形式:
- var obj = new Object; //obj = {}
- obj.name = "张三"; //添加描述
- obj.say = function(){}; //添加行为
除了以上添加属性的方式,还可以使用Object.defineProperty
定义新属性或修改原有的属性。
Object.defineProperty()描述
语法:Object.defineProperty(obj, prop, descriptor)
参数说明:
obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
返回值:
传入函数的对象。即第一个参数obj
针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写;是否可以被for..in
或Object.keys()
遍历。
给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。
数据描述
当修改或定义对象的某个属性的时候,给这个属性添加一些特性:
- var obj = {
- test:"hello"
- }
- //对象已有的属性添加特性描述
- Object.defineProperty(obj,"test",{
- configurable:true | false,
- enumerable:true | false,
- value:任意类型的值,
- writable:true | false
- });
- //对象新添加的属性的特性描述
- Object.defineProperty(obj,"newKey",{
- configurable:true | false,
- enumerable:true | false,
- value:任意类型的值,
- writable:true | false
- });
数据描述中的属性都是可选的,来看一下设置每一个属性的作用。
value
属性对应的值,可以使任意类型的值,默认为undefined
- var obj = {}
- //第一种情况:不设置value属性
- Object.defineProperty(obj,"newKey",{
- });
- console.log( obj.newKey ); //undefined
- ------------------------------
- //第二种情况:设置value属性
- Object.defineProperty(obj,"newKey",{
- value:"hello"
- });
- console.log( obj.newKey ); //hello
writable
属性的值是否可以被重写。设置为true可以被重写;设置为false,不能被重写。默认为false。
- 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
enumerable
此属性是否可以被枚举(使用for...in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false。
- var obj = {}
- //第一种情况:enumerable设置为false,不能被枚举。
- Object.defineProperty(obj,"newKey",{
- value:"hello",
- writable:false,
- enumerable:false
- });
- //枚举对象的属性
- for( var attr in obj ){
- console.log( attr );
- }
- //第二种情况:enumerable设置为true,可以被枚举。
- Object.defineProperty(obj,"newKey",{
- value:"hello",
- writable:false,
- enumerable:true
- });
- //枚举对象的属性
- for( var attr in obj ){
- console.log( attr ); //newKey
- }
configurable
是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被删除或不可以重新设置特性。默认为false。
这个属性起到两个作用:
目标属性是否可以使用delete删除
目标属性是否可以再次设置特性
- //-----------------测试目标属性是否能被删除------------------------
- 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
除了可以给新定义的属性设置特性,也可以给已有的属性设置特性
- //定义对象的时候添加的属性,是可删除、可重写、可枚举的。
- var obj = {
- test:"hello"
- }
- //改写值
- obj.test = 'change value';
- console.log( obj.test ); //'change value'
- Object.defineProperty(obj,"test",{
- writable:false
- })
- //再次改写值
- obj.test = 'change value again';
- console.log( obj.test ); //依然是:'change value'
提示:一旦使用
Object.defineProperty
给对象添加属性,那么如果不设置属性的特性,那么configurable
、enumerable
、writable
这些值都为默认的false
- var obj = {};
- //定义的新属性后,这个属性的特性中configurable,enumerable,writable都为默认的值false
- //这就导致了newkey这个是不能重写、不能枚举、不能再次设置特性
- //
- Object.defineProperty(obj,'newKey',{
- });
- //设置值
- obj.newKey = 'hello';
- console.log(obj.newKey); //undefined
- //枚举
- for( var attr in obj ){
- console.log(attr);
- }
设置的特性总结:
value: 设置属性的值
writable: 值是否可以重写。true | false
enumerable: 目标属性是否可以被枚举。true | false
configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false
存取器描述
当使用存取器描述属性的特性的时候,允许设置以下特性属性:
- var obj = {};
- Object.defineProperty(obj,"newKey",{
- get:function (){} | undefined,
- set:function (value){} | undefined
- configurable: true | false
- enumerable: true | false
- });
注意:当使用了getter或setter方法,不允许使用writable和value这两个属性
getter/setter
当设置或获取对象的某个属性的值的时候,可以提供getter/setter方法。
getter 是一种获得属性值的方法
setter是一种设置属性值的方法。
在特性中使用get/set属性来定义对应的方法。
- var obj = {};
- var initValue = 'hello';
- Object.defineProperty(obj,"newKey",{
- get:function (){
- //当获取值的时候触发的函数
- return initValue;
- },
- set:function (value){
- //当设置值的时候触发的函数,设置的新值通过参数value拿到
- initValue = value;
- }
- });
- //获取值
- console.log( obj.newKey ); //hello
- //设置值
- obj.newKey = 'change value';
- console.log( obj.newKey ); //change value
注意:get或set不是必须成对出现,任写其一就可以。如果不设置方法,则get和set的默认值为undefined
通过Object.defineProperty给一个对象的某个属性添加多个方法,如下例子:
- var obj = {};
- Object.defineProperty(obj,'atrr',{
- get:function(){
- var self = this;
- var num = 0;
- return {
- add:function(value){
- return num + value;
- },
- reduce:function(value){
- return num - value;
- }
- }
- }
- });
- console.log(obj.atrr.add(5)); //
- console.log(obj.atrr.add(8)); //
- console.log(obj.atrr.reduce(8)); //-8
说明:在obj对象的atrr对象上添加了两个方法add与reduce.
兼容性
在ie8下只能在DOM对象上使用,尝试在原生的对象使用 Object.defineProperty()
会报错。
参考
相关阅读:《JS基础篇--JS中的可枚举属性与不可枚举属性以及扩展 》
JS apply的巧妙用法以及扩展到Object.defineProperty的使用的更多相关文章
- js apply的用法
问题: 1.apply和call的区别在哪里 2.什么情况下用apply,什么情况下用call 3.apply的其他巧妙用法(一般在什么情况下可以使用apply) 我首先从网上查到关于apply和ca ...
- Js apply方法与call方法详解 附ES6新写法
我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里我做如下笔记,希望和大家 ...
- [荐]Js apply()和call()方法详解 - http://www.w3cfuns.com/article-5596443-1-1.html
本帖最后由 默默DE人生 于 2013-3-19 13:22 编辑 Js apply方法详解我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文 ...
- Js apply 方法 详解
Js apply方法详解 我在一开始看到JavaScript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- Js apply() call()使用详解
Js apply方法详解我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里 ...
- Js apply call方法详解
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- apply和call用法
资料来源:http://blog.csdn.net/business122/article/details/8000676 Js apply方法详解 我在一开始看到javascript的函数apply ...
- Js apply()使用详解
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- Js apply方法详解,及其apply()方法的妙用
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
随机推荐
- 解决Django项目数据库无法迁移问题
找到自己的虚拟环境,以下是我自己的环境路径 D:\xunihuanjing\venv\Lib\site-packages\django\contrib\admin\migrations 然后删除里面的 ...
- Emmet/Zen Coding 快速入门说明
快速参考 以下是支持的特性: ele creates an HTML element tag 展开一个HTML元素标签 # creates an id attribute 作用于元素标签,展开一个id ...
- vue webpack配置解决跨域问题
现在基本项目都是实行前后端分离的原则,不管是ng 或者是vue 在开发中都无法避免跨域的这个问题 本人刚上手第一个vue项目,在调用api的时候出现了跨域的这个问题 这是封装好一个简单的post 请求 ...
- c++中的左值与右值
左值(lvalue)和右值(rvalue)是 c/c++ 中一个比较晦涩基础的概念,不少写了很久c/c++的人甚至没有听过这个名字,但这个概念到了 c++11 后却变得十分重要,它们是理解 move/ ...
- sql server I/O硬盘交互
一. 概述 sql server作为关系型数据库,需要进行数据存储, 那在运行中就会不断的与硬盘进行读写交互.如果读写不能正确快速的完成,就会出现性能问题以及数据库损坏问题.下面讲讲引起I/O的产生, ...
- 微信小程序-canvas绘制文字实现自动换行
在使用微信小程序canvas绘制文字时,时常会遇到这样的问题:因为canvasContext.fillText参数为 我们只能设置文本的最大宽度,这就产生一定的了问题.如果我们绘制的文本长度不确定或者 ...
- 编码(2)从字节理解Unicode(UTF8/UTF16)
https://www.cnblogs.com/zizifn/p/4716712.html 从字节理解Unicode(UTF8/UTF16) 如果你不知道或者不了解什么是Unicode/UTF8/UT ...
- 完整例子-正则控制input的输入
转 : https://www.cnblogs.com/ckf1988/p/5619337.html
- 记录一下对swiper4.x.js在H5单页中的滑动优化
应用场景 仅仅应用于单页应用的滑动操作,用swiper4.x接管页面的滚动操作.用来支持顶部和尾部的回弹效果,进一步来支持常见那种下拉刷新动画效果.不适用于轮播图那种应用场景. 虽然只是针对swipe ...
- MySQL高可用之组复制技术(2):配置单主模型的组复制
MySQL组复制系列文章: MySQL组复制大纲 MySQL组复制(1):组复制技术简介 MySQL组复制(2):配置单主模型的组复制 MySQL组复制(3):配置多主模型的组复制 MySQL组复制( ...