飞道的博客

JavaScript知识点学习笔记-持续更新中

560人阅读  评论(0)

事件委托

利用冒泡的原理,把事件加到父级上,触发执行效果
event.target target.nodeName来判断是哪个标签

优点:

1、减少事件注册,节省内存。比如,

在table上代理所有td的click事件。
在ul上代理所有li的click事件。
2、简化了dom节点更新时,相应事件的更新。比如

不用在新添加的li上绑定click事件。
当删除某个li时,不用移解绑上面的click事件。

缺点:
1、事件委托基于冒泡,对于不冒泡的事件不支持。
2、层级过多,冒泡过程中,可能会被某层阻止掉。
3、理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。
4、把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。

//例子
<body>
    <div id="div1"></div>
</body>

window.onload = function(){
    let body = document.querySelector('body');
    let div1 = document.getElementById('div1');
    body.addEventListener('click',function(){
        console.log('打印body')
    })
    div1.addEventListener('click',function(){
        console.log('打印div1')
    })
}

文档碎片

document.createDocumentFragment() 一个容器,用于暂时存放创建的dom元素


原型模式的优缺点:

1、优点:可以让所有的对象实例共享它所包含的属性和方法

2、缺点:原型中是所有属性都是共享的,但是实例一般都是要有自己的单独属性的。所以一般很少单独使用原型模式。

prtotype、proto、constructor
◆每一个构造函数,都有一个原型[[prototype]]属性 指向构造函数的原型对象
◆每一实例化对象都有一个隐式原型_proto_ 指向构造函数的原型对象
◆每一个原型对象都有一个默认的constructor属性,指向对象的构造函数


闭包

指的是:能够访问另一个函数作用域的变量的函数
《JavaScript高级编程》书中建议:由于闭包会携带包含它的函数的作用域,因为会比其他函数占用更多内容,过度使用闭包,会导致内存占用过多。

//例如:
function init() {
    var name = "Mozilla"; // name 是一个被 init 创建的局部变量
    function displayName() { // displayName() 是内部函数,一个闭包
        alert(name); // 使用了父函数中声明的变量
    }
    displayName();
}
init();

js链式作用域(冒泡同理):
子对象会一级一级向上寻找所有父对象的变量,反之不行。

js变量两种作用域:
全局变量、局部变量(函数内):js中函数内部可以读取全局变量,函数外部不能读取函数内部的局部变量。

闭包为什么可以实现在函数外读取到函数内的变量:
原因:init是displayName的父函数,displayName被赋给了一个全局变量,displayName始终存在内存中,displayName的存在依赖init因此init也始终存在内存中,不会在调用结束后,被垃圾回收机制回收。


class es6

super()===A.prototype.constructor.call(this)

super可以造访继承的父级原型对象、可访问父级的原型方法(针对static静态方法调用)


array数组的增删改查排序

增加:

push() 方法可向数组的末尾添加一个或多个元素
unshift()  方法是向数组头部添加一个或多个元素,使用上同push方法
concat() 连接两个或以上的数组,返回的是一个新数组,不影响原数组

删除:

pop() 方法删除数组最后一个元素,该方法会改变原数组,删除元素并且数组长度-1,返回值是删除的元素的值,如果数组是空数组,则不进行删除,返回值是undefined 
shift() 方法删除数组第一个元素,使用上同pop方法

修改:

slice(start,end) 数组的截取函数,start 必需,end 选填 ,均可以为负数,返回的是start到end(不包括end)之间的元素,返回新数组,不影响原来数组 (slice 切开)
splice(index,howmany,item1,.....,itemX) 方法删除或者添加数组,会操作原数组,返回的是含有被删除的元素的数组,index 必需 起始位置,howmany 必需 数量可以为0,即不操作,第三个参数添加到数组 替代数组index的位置

排序:

 sort() 对数组进行排序,改变的是原数组元素顺序,默认是按字符编码排序,所以在遇到数字排序时,就需要定义函数
reverse() 颠倒元素顺序,改变原数组

其他:

indexOf() 找出某个元素在数组中的索引,并返回该元素索引。
join() 方法将数组拆分成字符串,返回值字符串,默认分隔符为逗号“,”
toString() 将数组转换成字符串,返回字符串,格式为逗号隔开

Object属性方法

var obj = { 0: "a", 1: "b", 2: "c"}; // 以下示例以此对象为例
//属性:

Object.prototype.writable//:默认为false 
Object.prototype.enumerable//:默认为false 
Object.prototype.configurable//:默认为false 
Object.prototype.constructor//:用于创建一个对象的原型。 

//常用方法:
Object.prototype.hasOwnProperty()//:返回一个布尔值,表示某个对象是否含有指定的属性,而且此属性非原型链继承。

Object.prototype.isPrototypeOf()//:返回一个布尔值,表示指定的对象是否在本对象的原型链中。

Object.prototype.propertyIsEnumerable()//:判断指定属性是否可枚举。

Object.prototype.toString()//:返回对象的字符串表示。

Object.prototype.watch()//:给对象的某个属性增加监听。

Object.prototype.unwatch()//:移除对象某个属性的监听。

Object.prototype.valueOf()//:返回指定对象的原始值。

Object.create(proto,[propertiesobject])//:创建一个拥有指定原型和若干个指定属性的对象。

Object.keys(obj) = Object.getOwnPropertyNames(obj).sort()//:返回一个由给定对象的所有可枚举自身属性的属性名组成的数组
	//举例:
	console.log(Object.getOwnPropertyNames(obj).sort()); //["0", "1", "2"]
	Object.keys(obj)//["0", "1", "2"]

Object.values(obj)//:返回一个包含指定对象所有的可枚举属性值的数组,数组中的值顺序和使用for…in循环遍历的顺序一样。
	//举例:
	Object.values(obj);//["a", "b", "c"]

Object.entries(obj)//:返回一个包含由给定对象所有可枚举属性的属性名和属性值组成的 [属性名,属性值] 键值对的数组,数组中键值对的排列顺序和使用for…in循环遍历该对象时返回的顺序一致。 
	//举例: 
	console.log(Object.entries(obj)); // [["0","a"],["1","b"],["2","c"]]

Object.assign(target, …sources)//:参考数组操作方法concat(),把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
	//举例:
	Object.assign(obj,{3:'d'},{4:'e',5:'f'});//{0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f"}

	

//不常用的方法:

Object.getPrototypeOf(object)//:返回该对象的原型。

Object.is(value1, value2)//:判断两个值是否是同一个值。

Object.isExtensible(obj)//:判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

Object.isFrozen(obj)//:判断一个对象是否被冻结(frozen)。

Object.isSealed(obj)//:判断一个对象是否是密封的(sealed)。密封对象是指那些不可 扩展 的,且所有自身属性都不可配置的(non-configurable)且属性不可删除的对象(其可以是可写的)。

Object.freeze(obj)//:冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。

Object.getOwnPropertyDescriptor(obj, prop)//:返回指定对象上一个自有属性对应的属性描述符。

Object.defineProperties(obj, props)//:在一个对象上添加或修改一个或者多个自有属性,并返回该对象。

Object.defineProperty(obj, prop, descriptor)//:直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。obj:需要定义属性的对象。prop:需定义或修改的属性的名字。descriptor:将被定义或修改的属性的描述符。


Set 和 Map es6

相同点:Set和Map都可以用来生成新的 Map
例:

 var  a = [['foo', 1],['bar', 2]];
	new Map(new Set(a)) === new Map(a) === Map(2) {"foo" => 1, "bar" => 2}
// 当然上例虽然值是相等的但是实际并不相等,这里只是看结果,因为Map 的键实际上是跟内存地址绑定

不同点:
1、Set适合操作数组,Map适合操作对象
2、Map具有set(key, value)和get(key)方法操作数据 Set使用add(value)方法

set 不重复的值的集合 es6

使用:new set()

//数组去重:
1[...new Set(array)]
2、Array.from(new Set(array))
//字符串去重
[...new Set(string)].join('')

遍历:

方法 同Object  :因为Set方法内部为对象形式。
new Set().add('a').add('b').forEach(data=>{console.log(data)}) //a //b
方法 同array    :具有数组的特性  
for(let data of new Set().add('a').add('b').keys()){console.log(data)} //a //b

map

同Set


Echarts

实现方式 纯 js 实现,MVC 封装,利用canvas绘制图形
特点:重要性和优先级依次递减,设计效果直观、生动,能够交互,可个性化定制。

MVC 架构:
Storage(M):模型层,实现图形数据的CURD(增删改查)管理;
Painter(V): 视图层,实现canvas 元素的生命周期管理,即:视图渲染、更新控制、绘图;
Handler©:控制层,事件交互处理,实现完整的dom事件模拟封装。


Proxy es6

代理拦截

//target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
var proxy = new Proxy(target, handler);

js内存分配(垃圾回收机制)

内存生命周期
不管什么程序语言,内存生命周期基本是一致的:

1、分配你所需要的内存
2、使用分配到的内存(读、写)
3、不需要时将其释放\归还 (对象有没有其他对象引用到它)

垃圾回收

  1. 引用:如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收 标记-清除算法 从根(全局对象)开始
  2. 将可能被引用的对象用递归的方式进行标记,然后将没有标记到的对象作为垃圾进行回收。

Promise构造函数 es6

语法:

new Promise( function(resolve, reject) {...} /* executor */  );

方法

Promise.all()  
Promise.allSettled()   
Promise.any()  
Promise.prototype.catch()
Promise.prototype.finally()
Promise.prototype.then()
Promise.race()
Promise.reject()
Promise.resolve()

有以下几种状态:
pending: 初始状态,既不是成功,也不是失败状态。
fulfilled: 意味着操作成功完成。
rejected: 意味着操作失败。

Promise + axios +qs 同步操作

关键字说明:
async:放在函数声明之前,使其成为 async function
await:它会暂停代码在该行上,直到 promise 完成

//模拟ajax异步操作1
   function ajax1() {
       const p = new Promise((resolve, reject) => {
           this.$axios({
	          url: '',
	          method: 'POST',
	          data: this.qs.stringify({a:1})
	        }).then(function (res) {
	          resolve(res.data)
	        })
   })
       return p
 
   }
       //模拟ajax异步操作2
   function ajax2() {
       const p = new Promise((resolve, reject) => {
           this.$axios({
	         url: '',
	          method: 'POST',
	          data: this.qs.stringify({a:1})
	        }).then(function (res) {
	          resolve(res.data)
	        })
   })
       return p
   }
   //等待两个ajax异步操作执行完了后执行的方法
  async function myFunction() {
       const x = await ajax1()
       console.log(x)
       const y = await ajax2()
       //等待两个异步ajax请求同时执行完毕后打印出数据
       console.log(x, y)
   }

Date日期时间戳获取转换

 //获取一个时间对象 可以添加时间或者时间戳 例如new Date(1594224000000)
var  time = new Date()   ;    
/*
*方法:
*/
var year = time.getFullYear() // 获取年
var month = time.getMonth(); // 获取月 注:月份从0开始计数 所以这里需要+1得到实际月份
var hour = time.getHours();  // 获取小时
var minute = time.getMinutes(); // 获取分钟
var second = time.getSeconds(); // 获取秒

/*
*将日期格式转换成时间戳:
*/
var time1 = date.getTime();
var time2 = date.valueOf();
var time3 = Date.parse(date);

//三种获取的区别:
time1 、time2:会精确到毫秒,其实这两种方法是有区别的在万为单位的获取中会有差异
time3:只能精确到秒,毫秒将用0来代替

/*
*date的几种参数形式 :
*月份从0~11
*/
// 
new date("month dd,yyyy hh:mm:ss"); 
new date("month dd,yyyy"); 
new date("yyyy/mm/dd hh:mm:ss"); 
new date("yyyy/mm/dd"); 
new date(yyyy,mth,dd,hh,mm,ss); 
new date(yyyy,mth,dd); 
new date(ms); // (1594224000000)

注:经常我们的日期格式会用“-”链接,也就是“2018-08-08”这种形式,放入以下方法有可能不会报错,但是手机浏览器会报错,避免不必要的麻烦,尽量转换成以下任意一种格式使用。


模块化开发

模块化是一种将系统分离成独立功能部分的方法,可将系统分割成独立的功能部分,严格定义模块接口、模块间具有透明性。

优点:
1、代码重用时,引入js文件的数目可能少了,避免来代码的累赘。
2、代码复用高,开发效率也会提高。
3、方便后期的维护

缺点:
1.系统分层,调用链会很长
2.模块间通信,模块间发送消息会很耗性能

常见的模块化的写法

1、原始写法(封装函数)

这种做法的缺点很明显:"污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。

2、对象写法

这样的写法会暴露所有模块成员,内部状态可以被外部改写

3、立即执行函数写法

立即执行函数可以达到不暴露私有成员的目的


解构赋值:es6

重点:
1、等号左边为var 的变量,右边为值得数组,两边通过key值一一赋值。
2、如果左边有属性赋值,就赋值右侧的对象属性。
3、只要等号右边的值不是对象或数组,就先将其转为对象 ,所以undefined和null 无法转换,会报错

简单了解解构赋值(数组的对象都有一个length属性):
以下例子统一变量 :

const 	str = '123', 
		value = [4, 5, 6],
		obj={a:7,b:8,c:9};

以下例子统一打印方法:

console.log('a='+a,'b='+b,'c='+c);

1、字符串: 变量 = 值

let [a,b,c]  = str;  
// 解析过程var [a,b,c][0]=str[0],[a,b,c][1]=key[1],[a,b,c][2]=[a,b,c][2];  
//结果var a=1,b=2,c=3;

2、数组:数组[0] = 数组[0]

let [a,b,c] = value  // 解析过程如上,结果为:var a=4,b=5,c=6;

3、对象:

let {a, b, c}  = obj;//解析过程如上,结果为:var a=7,b=8,c=9;

4、函数:这里涉及到解构赋值以及默认值方式,注意函数的结构赋值跟以上三种赋值方式一样,这里提供一个例子:

function add({x, y,z = 0}){
    			return x + y +z;
		}
		console.log(add({x : 1, y :2}))//3

5、属性赋值(以上讲的都是变量赋值,如果给变量添加属性,那么就是属性赋值):

let { valueOf: a } = obj;  // ƒ valueOf() { [native code] }

说明:上诉valueOf设置之后解析的就是obj的valueOf属性 如果设置其他属性同理。
这里打印出来a的值为 obj.prototype.valueOf

默认值: 所有定义的左侧变量都可以设置默认值 使用方式 ‘key=value’赋值,作用于右侧没有相关赋值操作后,保留默认值,否则更新值。
例如:

 let [a = 44,b,c,d = 77] = value  
 // 解析过程如上,
 //结果为:var a=4,b=5,c=6,d=77;

转载:https://blog.csdn.net/qq_27751965/article/details/107681017
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场