总结在项目中使用jQuery的$.extend()方法心得
最近在做的监控项目开发中,需要对监控到的数据在前端页面上进行展示,由于数据颇多,所以为了增强用户体验,对于数据的操作,我们一般会采用可视化效果的图标或者是数据插件,我这里用的是大家熟知的百度 echarts,当然还有其他优秀的插件,大家根据实际情况选择适合自己的插件。不管采用那种插件他们都有各自的配置项来实现这一效果,只要在项目中正确配置这些项目,运行界面就能达到我们想要的结果。
难道真的这么简单吗?No No No!作为一个开发人员我们要考虑到的是代码的扩展性和重复使用性,如果是简简单单直接写配置项,假如说我们有多个界面,我们在当前页面写了一次,难道到别的页面也要重写一次一样的配置吗,明显不可能,哪怕是简单的复制粘贴,如果现在在项目中总共有 100 个图表展示的地方,还有 100 个数据列表的展示,怎么办?因此,为解决扩展性和冗余性的问题,在代码设计过程中,我们就应当充分考虑到这些可能出现的问题,并做好解决的方案!
所以我的解决方法就是将他们公共的部分抽离出来写成一个可以调用的组件,重复使用,这样就可以避免代码的冗余,达到我们常说的组件化开发,而在开发的过程中就用到了 jQuery 的$.extend()方法,之前虽然有用到过,但是没有详细的记录一下这方面的知识,所以借此机会整理一下,为需要的小伙伴提供参考。
概述
用一个或多个其他对象来扩展一个对象,返回被扩展的对象。
如果不指定 target,则给 jQuery 命名空间本身进行扩展。这有助于插件作者为 jQuery 增加新方法。 如果第一个参数设置为 true,则 jQuery 返回一个深层次的副本,递归地复制找到的任何对象。否则的话,副本会与原对象共享结构。 未定义的属性将不会被复制,然而从对象的原型继承的属性将会被复制。
语法
$.extend( [deep ], target, object1 [, objectN ] );
deep
类型: Boolean
如果是 true,合并成为递归(又叫做深拷贝)。
target
类型: Object
对象扩展。这将接收新的属性。
object1
类型: Object
一个对象,它包含额外的属性合并到第一个参数。
objectN
类型: Object
包含额外的属性合并到第一个参数。
常见的用户输入数据时的设置
function getPeople(obj){ var default={ name: 'hunger', age: 20, sex: 'male' } var opts={} $.extend(obj,default,obj) console.log(opts); }
目标对象(第一个参数)将被修改,并且将通过$.extend()返回。然而,如果我们想保留原对象,我们可以通过传递一个空对象作为目标对象:
var object = $.extend({}, object1, object2);
例子:
function getPeople(obj){ var def={ name: 'hunger', age: 20, sex: 'male' } var opts=$.extend({},def,obj) console.log(opts) } obj2={ name: 'valley', age: 30 } getPeople(obj2);
最后输出 Object {name: “valley”, age: 30, sex: “male”}
说到这儿就要提到$.extend()方法的深拷贝与浅拷贝。
在默认情况下,通过$.extend()合并操作不是递归的(浅拷贝);如果第一个对象的属性本身是一个对象或数组,那么它将完全用第二个对象相同的 key 重写一个属性。这些值不会被合并。然而,如果将 true 作为该函数的第一个参数,那么会在对象上进行递归的合并(深拷贝)。
什么是深拷贝
深拷贝(true):如果第二个参数对象有的属性第一个参数对象也有,还要继续在这个相同的参数向下一层找,比较相同参数的对象中是否还有不一样的属性,如果有,将其继承到第一个对象,如果没有,则覆盖。
什么是浅拷贝
浅拷贝(false 默认):如果第二个参数对象有的属性第一个参数对象也有,那么不会进行相同参数内部的比较,直接将第一个对象的相同参数覆盖。
下面我们通过例子详细看一下:
$.extend()方法默认是浅拷贝
举栗子:
var obj={} var obj1={ name: 'hunger', sex: 'male', friends: [1,2,3] }; var obj2={ name: 'valley', age: 30 } $.extend(obj,obj1) //得到 obj={ name: 'hunger',sex: 'male',friends: [1,2,3]} //这个时候我们再进行以下操作 obj.friends[0]=100; //此时 obj={name: 'hunger',sex: 'male',friends: [100,2,3]} obj1.friends //输出[100,2,3] obj1 也会随之改变 这就是浅拷贝
$.extend()方法之深拷贝
要想实现深拷贝,则需要设置布尔值,这样写:$.extend(true,obj,obj1)
所以我们上面的例子改一下就是:
var obj={} var obj1={ name: 'hunger', sex: 'male', friends: [1,2,3] }; var obj2={ name: 'valley', age: 30 } $.extend(true,obj,obj1); //这个时候我们再进行以下操作 obj.friends[0]=100;//此时 obj={name: 'hunger',sex: 'male',friends: [100,2,3]} obj1.friends //输出[1,2,3] obj1 不会改变 这就是浅拷贝
项目中的应用(以实现 datagrid 为例)
首先,我们知道当前后两个参数相同的时候,后者会覆盖前者,因此,为满足配置项经可能的根据我们自己定义来实现,我们可以定义第一个 item(也就是$.extend()中的非第一个参数):
var basic = { title:'My Title', iconCls:'icon-save', nowrap: true, striped: true, border: true, fitColumns: true, fit:true, pagination:true, rownumbers:true, singleSelect: false, loadMsg: '数据正在努力加载...' }
接着,在我们要实例化一个 datagrid 数据表格的地方,根据不同配置,来进行个性化定义:
var config = { url:/test/data.json, columns: [[ {field:'ck',checkbox:true}, {field: 'datetime', title: '日期', align: "center",width:100}, {field: 'flows', title: '流量', align: "center",width:100} ]], }
得到了我们想要的配置 config 后,我们就要祭出我们的大熔炉 extend()方法啦!
var myOptions = $.extend({},basic,config); $("#datagrid").datagrid(myOptions);
这样只需要通过配置不同情况下的 config,就可以得到不同的 datagrid 数据列表啦!并且我们可以通过封装 basic 为一个工具文件,在需要应用它 的地方引入他就可以轻松实现实例化,大功告成!
ECharts 组件封装
我在监控项目中的 echarts 封装代码附上,仅供参考!
!(function() { "use strict"; var _map_chart = {}; var _map_socket = {}; var echarts_option = { title: { text: '', subtext: '' }, color: ['#7cb5ec', '#90ed7d', '#FE8463', '#9BCA63', '#FAD860', '#60C0DD', '#0084C6'], xAxis: { type: 'category', boundaryGap: false, name: '时间' }, yAxis: { type: 'value', name: '', offset: '0', position: 'left', scale: true, nameTextStyle: { fontSize: 12, align: 'right' } }, dataZoom: [{ type: 'inside' }], vislaMap: [{ calculable: false }], tooltip: { show: true, trigger: 'axis', triggerOn: 'mousemove|click' }, grid: { bottom: 40, left: 80, top: 60 }, legend: { show: true, top: 'bottom', selectedMode: false, animation: false }, dataset: { source: [] }, series: [] }; var socket = function(id, url, args, dataName) { var ws; if ("WebSocket" in window) { ws = new WebSocket("ws://" + window.location.host + contextPath + "/websocket/" + url + "?host=" + args["host"] + "&port=" + args["port"] + "&range=" + args["range"] + "&type=" + args["type"]); } else { ws = new SockJS(contextPath + "/sockjs/" + url + "?host=" + args["host"] + "&port=" + args["port"] + "&range=" + args["range"] + "&type=" + args["type"]); } ws.onopen = function(event) {} ws.onclose = function(event) {} ws.onmessage = function(event) { var msg = event.data; var data = eval('(' + msg + ')'); var _chart = _map_chart[id]; if($.isArray(data)) { _chart.setOption({ dataset: { source: data } }); }else if(dataName && data[dataName]){ _chart.setOption({ dataset: { source: data[dataName] } }); } _chart.hideLoading(); } ws.onerror = function() {} _map_socket[id] = ws; }; var chart = { init: function(id, url, option, args) { var _chart = echarts.init(document.getElementById(id)); _chart.showLoading({ text: '数据正在努力加载...', textStyle: { fontSize: 30, color: '#444' }, effectOption: { backgroundColor: 'rgba(0, 0, 0, 0)' } }); var _option = $.extend(true, {}, echarts_option, option) _chart.setOption(_option); _map_chart[id] = _chart; socket(id, url, args, option.dataName); return _chart; }, destory: function(id) { echarts.dispose(document.getElementById(id)); var ws = _map_socket[id]; try { if (ws.readyState != WebSocket.CLOSED) { ws.close(); } } catch (e) {} _map_socket[id] = undefined; _map_chart[id] = undefined; }, reload: function(id, url, option, args) { this.destory(id); this.init(id, url, option, args); } }; if (!window.chart) { window.chart = chart; } })();
结束语
以上就是 jQuery 的$.extend()用法总结的详细内容,仔细阅读上面代码例子,亲自去运行看结果,相信你就会理解什么是深拷贝和浅拷贝了!更多请关注码云笔记其它相关文章!
码云笔记 » 总结在项目中使用jQuery的$.extend()方法心得