jQuery2

2018-11-28  本文已影响0人  fastwe

第三章*****************************************************************************************

1.ES5:

ECMAScript: ECMA组织制定的JavaScript语言的国际标准,规定了JS语言的核心语法

ES5是ECMAScript的第五个版本(第四版过于复杂废弃了),IE8部分此版本

保护对象:

什么是:① 保护对象的属性和属性值始终有意义

       ② 防止篡改对象的结构

为什么:① 对象的属性,默认可随意赋值

       ② 对象可随意添加、删除属性

何时: 严格来说,今后所有对象,都要有自我保护的抵抗力

如何: 分为保护属性和防篡改

保护属性: 保护对属性值的修改

对象属性分为:

命名属性: 可通过.直接访问的属性

    分为: 数据属性: 直接保存属性值的属性

          访问器属性: 不直接存储属性值,仅提供对其他数据属性的保护

内部属性: 无法通过.直接访问的属性

数据属性的四大特性:

value:实际存储属性值

writable:true/false控制属性是否可修改属性值

enumerable:true/false控制属性是否可被for in遍历(false会跳过),仅控制遍历,无法控制用.访问

configurable:true/false控制是否可删除该属性,控制是否可修改其它两个特性

强调: configurable经常作为前两个属性的双保险,且一旦设为false,不可逆

获取四大特性:

Object.getOwnPropertyDescriptor(obj,"属性名")

设置1个属性的四大特性:

Object.defineProperty(obj,"属性名",{

  要修改的特性:特性值,

  要修改的特性:特性值,

  ... ...

})

问题: defineProperty一次只能修改一个属性

解决: 同时修改多个属性的特性:

Object.defineProperties(obj,{

  属性名:{ 要修改的特性 },

  属性名:{ 要修改的特性 },

  ... : ...

})

添加属性: 可用defineProperty添加新属性

          只要defineProperty要修改的属性不存在,就会自动添加

强调: 用defineProperty添加的新属性,四大特性默认值都为false

而用.添加的新属性,四大特性默认值都为true

问题: 无法使用自定义逻辑保护属性

解决: 访问器属性

_______________________________________________________________________________________________

访问器属性: 不直接存储属性值,仅提供对其他数据属性的保护

何时: 只要使用自定义的规则保护属性值

为什么: 数据属性的四大特性,保护规则是固定的,无法自定义

如何定义: 2步:

①定义一个隐藏的数据属性,用于实际存储属性值

②再定义一个访问器属性,保护隐藏的数据属性:

Object.defineProperty(obj,"属性名",{/*或用defineProperties,不能通过直接量或.创建*/

 get(){                                  /*在试图获取属性值时自动调用*/    

    return this.隐藏的数据属性;           /*返回受保护的数据属性值*/

 },

 set(val){          /*在试图修改属性值时自动调用,参数val会自动获得要修改的新值*/

    if(...)                /*验证val是否符合规则*/

      ...                  /*将val赋值给受保护的属性*/

    else ...               /*否则*/

      throw new Error      /*主动抛出错误*/

 },

enumerable:true,          /*设置四大属性*/

configurable:false

})

如何使用: 只要定义了访问器属性,就优先使用访问器属性,而不用受保护的数据属性

          访问器属性的用法和普通属性用法完全一样

          但是: 在取值时,自动调用get()

                在赋值时,自动调用set(),val会自动获得要赋的新值

内部属性: 无法通过.直接访问的隐藏属性

          比如: __proto__

_______________________________________________________________________________________________

防篡改: 阻止对对象结构的修改

3个级别:

①防扩展: 禁止添加新属性

Object.preventExtensions(obj)

  原理: 每个obj内部都有一个隐藏属性: Extensible,默认为true

        preventExtensions将obj的Extensible改为false

②密封: 在防扩展的基础上,进一步禁止删除现有属性(两个不要一起用)

Object.seal(obj)

  原理: 将obj的Extensible改为false

        将所有属性的configurable都自动改为false

③ 冻结: 在密封基础上禁止修改一切属性值(过于严格)

Object.freeze(obj)

  原理: 修改obj的Extensible为false

        将所有属性的configurable都改为false

        还将所有属性的writable都改为false

_______________________________________________________________________________________________

Object.create(): 本质上是创建一个新的子对象

什么是: 基于一个现有父对象,创建一个新的子对象继承当前父对象,并扩展新属性

何时: 今后如果没有构造函数的情况下,也想创建子对象

如何:

var child=Object.create(father,{      /*若不用扩展自有属性,father后的内容不必写*/

  自有属性:{

    value:值,

    writable:true,

    enumerable:true,

    configurable:true,

  },

  ... : {

    ...

  }

});

强调: 只要添加到对象中的属性,四大特性默认为false,必须显式写为true

原理:① 创建一个空对象

     ② 让新对象自动继承father

     ③ 为新对象扩展新的自有属性

_______________________________________________________________________________________________

call/apply/bind:

共同:为了替换函数中不想要的this

何时: 只要函数中的this不是想要的 (函数不加括号,只在call/apply/bind右边加括号)

call和apply:

什么是:强行调用一个函数并临时替换函数中的this为指定的新对象

call:  要求传入函数的参数必须单独传入,逗号分隔

第1个参数是要指定的this,第2,3...个是要替换的参数

apply: 要求传入函数的参数,必须放入数组中整体传入

       apply可自动打散数组类型的参数,单个传入

第1个参数是要指定的this,第2个参数是一个数组

bind:  基于一个现有函数创建一个功能完全相同的新函数,并永久绑定this为指定对象

       还可永久绑定部分固定的参数值

替换回调函数中的this时,都用bind

比如: var newFun=fun.bind(obj)    //接收新参数,函数后添加

             newFun(参数1,...);          //调用函数

强调: 被bind永久绑定的this,不能再被call/apply临时替换

_______________________________________________________________________________________________

数组API:

判断: 判断数组中的元素是否符合要求

返回值:bool(可判断是否满足条件)

①every: 判断数组中所有元素是否都满足要求

var bool = arr.every(function(val,i,arr){  //回调函数: 当前元素值:val;当前元素位置:i;arr:当前数组

  return 判断条件

});

②some: 判断数组中是否包含满足条件的元素

var bool = arr.some(function(val,i,arr){

  return 判断条件

});

强调:数组API的回调函数中this默认->window,所以,不能用this指代当前元素值,但可用如arr[i]或val

遍历: 对数组中每个元素执行相同的操作:

①forEach: 对原数组中每个元素执行相同的操作

arr.forEach(function(val,i,arr){    //没有返回值

  arr[i]=新值;                      //对当前元素执行的操作,直接修改原数组,只能使用arr[i]

})

②map: 取出原数组中每个元素,执行相同操作后,再放入新数组返回

var arr2 = arr1.map(function(val,i,arr){        //返回一个新数组

  return 对当前元素操作后的新值(放入新数组中)        //不修改原数组,使用arr[i]=..可修改原数组

})

过滤和汇总:

过滤: filter: 复制原数组中符合条件的元素,组成新数组

var subArr=arr.filter(function(val,i,arr){

  return 判断条件        //筛选出arr中符合判断条件(为true)的元素值,放入新数组返回

})

汇总: reduce: 将数组中所有元素,统计出一个汇总结果

var r=arr.reduce(function(prev,val,i,arr){       //prev: 截止目前的临时汇总值

  return prev+val

},startVal);                           //startVal: 表示汇总开始的基数,可不写(默认为0)

将arr数组中每个值累加后,求和

强调: reduce不一定非要从0开始累加,可从任意startVal(也可以是其它数组)开始累加

_______________________________________________________________________________________________

严格模式:

什么是: 比普通js运行模式要求更严格的运行机制

为什么: 解决普通js运行模式中广受诟病的缺陷

何时: 今后都要在严格模式下开发

① 新项目, 必须全部启用严格模式

② 旧项目, 逐个函数向严格模式迁移

如何: 2种:

① 整个代码段启用严格模式:

在<script>标签或js文件的开头加入:"use strict";

② 仅对单个函数启用严格模式

仅在function内,函数体的顶部加入:"use strict";

要求:

1. 不允许对未声明的变量赋值

2. 静默失败升级为错误

3. 不推荐使用arguments.callee来实现递归

_______________________________________________________________________________________________

2.ES6(框架广泛采用,又称为ECMAScript 2015):

模板字符串: 对字符串拼接的简化(2015年首次发布,IE Edge不支持)

何时: 如果字符串中包含需要动态执行的表达式或回车换行时

如何:3件事

① 用``反引号(ESC键的正下方)包裹字符串

② 字符串中的变量和表达式都要放在${...}中

③ 模板字符串中支持:  换行,变量,表达式(),注释也会被解析

let:

1. 专门声明仅在当前块中有效的局部变量

  块: js中只要一个{}就是一个代码块

      let声明的变量,仅在{}内有效,不会被提前到{}外

2. 防止声明提前现象

声明提前: 在开始执行程序前,引擎会将var声明的变量和function声明的函数,提前到"当前作用域"顶部集中优先创建,再开始执行程序            /*但是赋值留在原地*/

何时:今后强烈建议用let代替var

强调:let必须配套严格模式使用

_______________________________________________________________________________________________

箭头函数: 对所有回调函数的终极简写

何时: 今后,几乎所有的回调函数,都要用箭头函数简化

如何:

1.所有回调函数都可:去 function(参数) 改为 (参数)=>

2.如果函数体只有一句话: 可省略{}

如果这一句话还是return,可省略return

3.如果只有一个参数:可省略()

但是,如果没有参数,必须保留空()

特点:箭头函数可让内外this共用同一个对象————不再需要bind替换

特殊: 如果不希望内外共用this,就不能用箭头函数(或者用e.target -> 当前单击的元素对象)

比如事件处理函数:

  elem.addEventListener("click",function(){ this -> 当前单击的元素对象,不共用 })

  elem.addEventListener("click",()=>{ 致使this -> 不是elem })

变通解决:

elem.addEventListener("click",e=>{ e.target->elem })    /*利用冒泡*/

特点:

① 箭头函数没有this

② 箭头函数没有arguments

③ 不能通过 new 关键字调用

④ 没有 new.target

⑤ 没有原型

⑥ 没有 super

_______________________________________________________________________________________________

for of: 简化for循环遍历:

何时: 直接获得每个元素值时

如何:

for(var i=0;i<arr.length;i++){ arr[i] }       /*arr[i]: 当前元素*/

简写为:

for(var val of arr){ val }            /*val: of会依次取出arr中每个元素的值,保存到val*/

局限:

①只能遍历索引数组和类数组对象,不能遍历关联数组和对象(只能用for in循环遍历)

② 无法获得下标

③ 只能逐个遍历所有,不能控制循环的开始和结束以及步调

④按值传递: 如果数组中保存的是原始类型的值,修改val,不会影响数组元素(val是数组元素值的副本)

何时:仅遍历元素值,不关心下标时,才可用for of简写

_______________________________________________________________________________________________

class: 对 面向对象 的简化

如何定义类型:

①用一个 class 类型名{}结构包裹原来的 构造函数和原型对象方法

②修改构造函数的'function'为'constructor',其余保持不变

③可省略开头的'类型.prototype'与方法名后的'=function'

直接定义在class中的函数直接量,会自动保存在当前类型的原型对象中

定义父类:

class Flyer{

  constructor(fname,speed){

    this.fname=fname;

    this.speed=speed;

  }

  fly(){ }        //fly <=> Flyer.prototype.fly

  get 访问器属性名(){ return this.受保护的其他属性 }    //添加访问器属性,在构造函数的平级

  set 访问器属性名(val){

    if(条件) this.受保护的属性=val

    else 报错

  }

}

继承: 不再设置Object.setPrototypeOf

①在'class 类型名'后添加'extends 父类型'名

② 在子类型构造函数中不允许直接用call调用父类型构造函数,可使用super(属性参数值列表),不加this

子类:

class Plane extends Flyer{             //让Plane继承Flyer

  constructor(fname,speed,score){

    super(fname,speed);  //super:关键字,指父类型的构造函数,自动将子类型的this传入父类构造函数中,不允许用call

    this.score=score;

  }

  getScore(){ }

}

使用:

var obj = new Plane('fname',10,30)    //也可以new父类: var obj = new Flyer('fname',10)

obj.getScore()        //子类的方法

obj.fly()             //父类的方法

上一篇下一篇

猜你喜欢

热点阅读