一、前言
1、[].slice.call(lis)将伪数组转化为真数组
2、node.nodeType: 得到节点类型
3、Object.defineProperty(obj, propName, {}): 给对象添加修改属性
4、Object.keys(obj)
5、DocumentFragment: 文档碎片(高效批量更新多个节点)
二、主要内容
1、[].slice.call(lis)将伪数组转化为真数组
(1)官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
(2)例子:在页面中通过标签名获取到的元素并不是一个真正的数组,
<ul id="fragment_test"> <li>test1</li> <li>test2</li> <li>test3</li> </ul> <script type="text/javascript"> //1.[].slice.call(this) 根据伪数组生成对应的真数组 const lis = document.getElementsByTagName("li") console.log(lis)//是一个特别的对象,有下标,有长度 </script>
打印出结果如下:这只是一个对象,并且这个对象里面包含下标,长度,看起来很像一个数组
(3)将伪数组转化为数组
//1.[].slice.call(this) 根据伪数组生成对应的真数组 const lis = document.getElementsByTagName("li") console.log(lis)//是一个特别的对象,有下标,有长度 console.log(lis instanceof Object, lis instanceof Array)//true false //数组的slice()截取数组中指定部分的元素,生成一个新的数组, const lis2 = Array.prototype.slice.call(lis) console.log(lis2 instanceof Object, lis2 instanceof Array) //true true
2、node.nodeType: 得到节点类型
(1)官网:https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeType
(2)
//2. node.nodeType:得到节点类型 const elementNode = document.getElementById('test') const attrNode = elementNode.getAttributeNode('id') //得到属性 const textNode = elementNode.firstChild //得到文本 console.log(elementNode.nodeType, attrNode.nodeType, textNode.nodeType)
3、Object.defineProperty(obj, propName, {}): 给对象添加修改属性(vue的数据代理中用到了这个原理)
(2)defineProperty里面的存取描述符get()和set()函数用来监听和读取数据的变化。
const obj = { firstName:'A', lastName:'B' } //给对象添加属性 Object.defineProperty(obj, 'fullName', { //属性描述符 /*configurable:false enumerable :false value:属性值 writable: */ //存取描述符: /* get:提供getter方法, set:监听属性值的改变 */ get(){//当读取此属性时自动调用,将函数返回值作为属性值 return this.firstName +"-" + this.lastName }, //当修改了对象的当前属性时自动调用,监视当前属性值的变化,修改相关属性 set(value){ const names = value.split('-') this.firstName = names[0] this.lastName = names[1] } }) console.log(obj.fullName)//A-B obj.fullName='C-D' //修改属性值 console.log(obj.firstName, obj.lastName) //监听到fullName属性发生变化,就会立即调用set方法
4、Object.keys(obj): 得到对象自身可枚举的属性名的数组(在数据代理的时候也有用到)
(1)官网:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
const obj = { firstName:'A', lastName:'B' } const names = Object.keys(obj) console.log(names)//[firstName, lastName]
5、DocumentFragment: 文档碎片(高效批量更新多个节点)
(1)官网:https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment
(2)举例:这个技术在vue中运用非常多,当我们需要比如下面我们需要将li标签里面的文字全部替换。按照传统的方式,需要获取到每个li标签,然后遍历每个li标签,最后操作每个li标签,如果页面中有无数个li, 用这种方式会频繁操作DOM,效率很低
(3)用文档碎片:来避免页面多次更新。文档碎片相当于是存在内存中的一个虚拟的DOM容器, 更新每个li的时候先让页面先不动,页面所有li都更新完了,然后在一次性批量操作页面。
<body> <ul id="fragment_test"> <li>test1</li> <li>test2</li> <li>test3</li> </ul> <script type="text/javascript"> //1.创建fragment var ul = document.getElementById('fragment_test') var fragment = document.createDocumentFragment() //2.取出ul中的所有子节点保存到fragment中 let child; while(child = ul.firstChild){ fragment.appendChild(child) console.log(ul.firstChild) } //3.更新fragment中所有li的文本 let lis = fragment.children;//得到的是一个伪数组 let lis2 = Array.prototype.slice.call(lis) for(var i=0; i<lis2.length; i++){ if(lis2[i].nodeType===1){//如果为元素节点 lis2[i].textContent='hello' } } //4.将fragment插入ul ul.appendChild(fragment) </script>
三、总结