JS笔记

方便起见不分parameter[形参,出现在函数定义中]和argument[实参,其值为传入函数的值],一律当作argument记录

javascript会在上下行无法合并解释时自动添加行末封号,++--加在前面,{}当与语句同行

1 改变元素内容:点击显示日期时间

<button onclick="document.getElementById('ID').innerHTML="/'html语句"/'">
内容
</button>
<p id="ID"></p>
  • 访问元素:document.getElementById('ID')

2 改变属性

<button onclick="document.getElementById('ID').属性='值'">内容</button>
<button onclick="document.getElementById('ID').属性.子属性='值'">内容</button>
  • 隐藏/显示元素
    <button onclick="document.getElementById('ID').style.display='none/block'">

3 外置脚本

<button onclick=函数名(参数)>内容</button>
<script>
function 函数名(参数){
    pass
}
</script>

<script src="文件"></script>
  • 放在head? body? 一般都放body吗?
  • 放body底部会加快加载速度

4 输出方式

  • 使用[window.]alert()写入警告框
  • 使用document.write()写入 HTML 输出
    • 会覆盖加载完的HTML文档,仅用于测试
  • 使用innerHTML写入HTML 元素
  • 使用console.log()写入浏览器控制台

5 变量[也可以初始化]

声明

  • var 变量名;

    • 弱类型,声明关键字无区别,可动态变化
    • 字母/_/$开头[数字: 字符串]
    • 命名: 小写打头的驼峰式
    • 自动提升[Hoisting]声明,但不提升初始化
    • 可以重新声明
  • let

    • 声明只在本作用于中可见的变量;
    • HTML中用let声明全局变量,不自动变成window的属性
    • 同一作用域中不能重新声明,不能重新声明var也不能被var重新声明
    • 没有自动提升
  • const常量

    • 可见方式和重复声明与let相同
    • 必须初始化
    • 声明成初始值→不可改;声明成对象→属性可改

类型

原始数据类型PrimitiveValue
  • 数字/number
    • 没有int/long/float/...的区别,实际存储的是字符串
    • 八/十六进制: 0/0x开头
    • [?]浮点数在计算前储存的是字符串
    • 科学计数法: 数字[正负号]e指数
  • 字符串/string ""/''
    • var 变量=""
    • 串内换行用\ [同python]
    • 属性与方法见String对象
  • undfined 类型和值都是undefined,是变量未被初始化时的类型,也是调用没有返回值的函数时出现的类型
    • 可用于清空值/取消引用
  • boolean
    • truely/falsely变量:!!a===true/false
  • Symbol
复杂数据类型
  • 对象[类]/object {key: value}[python: 字典]

    • var 对象={
          index1:{key11:value11, key12:value12, ...},
          index2:{key21:value21, key22:value22, ...},
          ...
      };
      
    • 被命名值的容器

    • 访问对象属性

      • property in 实例对象in检查对象是否拥有属性,不分辨为继承与否

      • for ([var] peoperty in 实例对象)

        • 顺着原型链找出实例对象的所有属性

          function inheriedPropertiyNames(obj){
              var props={};
              while(obj){
                  Object.getOwnPropertyNames(obj).forEach(function(p){
                      props[p]=true;  //将obj每个属性的同名属性放入props
                  });
                  obj=Object.getPrototypeOf(obj);
              }
              return Object.getOwnPropertyNames(props);
          }
          
    • 全局对象window

    • 创建实例[对象] var 变量(实例对象)=[引用]new Object[(value1, ...)] obj={}等价

    • 销毁/废除实例[对象] 变量(对象)=null

    • 作用域:只有公有,但习惯用对象._属性/方法_来表示私有;使用静态作用域

    • 对象的自带属性

      • constructor 引用构造函数的指针
      • prototype 引用对象原型的指针,原型链最终指向null;如果要改变,需要同时修改constructor.prototype
      • name 构造函数名称
      • __proto__ 对象的原型,尽量少用,用Object.getPrototypeOf(obj)
    • 对象的自带方法

      • 实例方法

        • hasOwnProperty(property) 判断是否为继承来的属性

        • isPrototypeOf(object) 调用此方法的对象是否是object的原型

        • propertyIsEnumerable()

        • toString/LocalString()

          👉Object.prototype.toString.call(实例)=[object 类型]否则实例所属的对象的toString()可能覆盖它

          var type=function (o){
              var s=Object.prototype.toString.call(o);
              //组匹配的第一个匹配的组的小写
              return a.match(/\[object (.*?)\]/)[1].toLowerCase();
          };//返回对象类型
          //遍历数组,对其中的每个值创造一个函数,作为对象type的属性"is+这个值"的值
          ['Null','Undefined','Object','Array','String','Number','Boolean','Function','RegExp'].forEach(function (t){ 
              type['is'+t]=function (o){
                  return type(o)===t.toLowerCase();
              };
          });
          
          type.isRegExp(/abc/);   //true
          
        • valueOf() 返回数值/原始值/对象本身[object 类型]

      • 静态方法

        • 属性

          • 属性描述对象attributeObject 的属性/元属性:

            • value:undefined 只要writable/configurable有一个true就能改

            • writable:true false时修改不会报错[严格模式会],但改不了

            • enumerable:true false:不可枚举/秘密,不可以for...in/Object.keys()/JSON.stringfy()读取

            • configurable:true false:不可删除,不可配置,value/writable/enumerable/configurable皆不可修改

            • get:undefined[writable必为false,不可同时定义value]

            • set:undefined

              var obj={
                  a:value,    //b属性依赖内部属性a
                  get b(){
                      return this.a;
                  },
                  set b(value){
                      if (条件) this.a=value;
                      else throw new Error('message');
                  }
              };
              obj.b;
              obj.b=value;
              
          • Object.getOwnPropertyDescriptor(实例,'属性')获取属性描述对象,不能用于继承的属性[如:方法]

          • Object.prototype/实例.propertyIsEnumerable('属性')

          • Object.keys(对象)[常用]/Object.getOwnPropertyNames(对象) 返回"属性名"数组,前者只返回可枚举属性

          • Object.defineProperty(object对象, propertyName属性名, atrributesObject属性描述对象)/Object.defineProperties (object, {propertyName:attributeObject})writable/confuguable/enumerable默认值为false

            var obj=Object.defineProperties({},{  //新建一个空对象
                p1:{value:1, enumerable:true, ...},
                p2:{value:2, enumerable:true, ...},
                p3:{get:function (){return this.p1+this.p2}}, ...}
            });
            
          • 对象的[深]拷贝

            //方法1
            var extend=function (to,from){
                for (var property in from){   //读取对象的属性
                    if(!from.hasOwnProperty(property)) continue;
                    Object.defineProperty(
                      to,
                        property,
                        Object.getOwnPropertyDiscription(from,property);
                    );
                }
                return to;
            }
            extent({},{get a(){return 1}});   //调用
            //方法2
            function copyObject(orig){
                return Object.create(
                  Object.getPrototypeOf(orig),
                    Object.getOwnPropertyDescriptors(orig)
                );
            }
            
        • 状态

          • Object.preventExtensions(实例) 使实例/对象无法添加新属性,如果尝试,严格模式下会报错

            👉Object.isExtensible(实例) 检查实例/对象是否可以添加新属性

          • Object.seal(实例) 不能增不能删,实为Object.getOwnPropertyDescriptor(对象, 属性).configurable=false

            👉Object.isSealed(实例)

          • Object.freeze(实例) 不能增不能删不能改,将实例/对象变为常量,如果尝试,严格模式下会报错

            👉Object.isFrozen(实例)if(!Object.isFrozen(实例)) ;

          • 绕过三者:使用var proto=Object.getPrototypeOf(实例);proto.属性=value;更改

          • 上述三种冻结只能冻属性指向某对象,不能冻结属性指向的值,如被冻结的实例.属性[值为一个数组].push('内容')可以发生

        • 原型链

          • Object.getPrototypeOf(obj)

          • Object.setPrototypeOf(被设置对象, 原型对象) 可以返回被设置对象

            var f=new F();
            //等同于
            var f=Object.setPrototypeOf({},F.prototype);
            F.call(f);
            
          • Object.create(obj) 返回以obj为模板的新对象,后者继承obj所有属性;obj不能是原始类型对象

            • var obj=Object.create(null) 一个没有valueOf()toString()的对象

            • obj1的修改会影响到obj2

            • 等效

              Object.create=function (obj){
                  function F(){}
                  F.prototype=obj;
                  return new F();
              }
              
            • 可以有第二个参数,给新对象新增属性,写法同Object.definePropertiesOf()的参数

    • 引用类型[≈子类?]

      • 数组/array [value 1, value 2, ...]

        • 数组名[下标]

        • length

        • 遍历 forEach(函数) function 函数(value项目值, index项目索引, array数组[可不全]) 会跳过空位但不跳undefined

          • map(函数[参数同上]) 对每个元素执行函数并创建新数组
          • filter(筛选函数) 对每个元素执行筛选函数并创建新数组
          • reduce/reduceRight(函数[, 初始值]) function 函数(total初始值/上一个返回值, value, index, array[可不全]) 对每个元素迭代函数并创建新数组
          • every(筛选函数) 所有通过返回true
          • some(筛选函数) 存在通过的返回true
        • 检索 indexOf(item[, start])/lastIindexOf(item[, start]) /find(func(value, index,array))/ findIindex(func(同前))

        • 添加 push(元素) 返回新数组长度/unshift() 在首位添加元素并移位,返回新数组长度

        • 删除 pop() 返回被删元素/shift() 删除首个元素并一并移位,返回被删元素/delete 数组[下标] 但会留下空洞empty

        • 数组[下标]=元素

        • 替换 splice(替换位置, 删除元素个数, 加入元素1, ...) 删除可>加入,不留空洞

        • 合并 concat(被合并数组1, ...)

        • 切片 slice(起始下标[, 终止下标/default=length-1])

        • 判断类型 Array.isArray(数组)/变量.constructor.toString(). indexOf("Array")/instanceof

        • 合并为字符串 toString(),分隔/join([分隔符])

        • 排序 sort() 按顺序根据字符编号排

          • 对数值排:加入比值函数数组.sort(function(a, b){return a-b}) 根据返回值正负摆放前后位置

          • 找最值:用sort()数组[0]数组[length-1]/调用Math.max.apply(null, 数组)/自定义

          • 在对象中排序:return a.key-b.key

        • 反转顺序 reverse()

        • Array对象

      • null 类型和值[字面量]都是null,“对象的占位符”

      • Boolean对象

      • Math对象

        没有构造函数,属性时常量,方法是函数,不必为此创建一个对象后调用

        • PI/E/SQRT2/SQRT1_2/LN2/LN10/LOG2E/LOG10E

        • round/ceil/floor(x)四舍五入/向上/向下取整

        • pow(x, y) x的y次方

        • log(x) ln(x)

        • sqrt(x)

        • abs(x)

        • exp() 科学记数法

        • sin/cos/tan(rad)

        • asin/acos/atan(x)[rad]/atan2(x,y)[°]

        • max/min(x1, x2, ...)

        • random() [0,1)间随机数

          function getRandOnt(min, max){
              return Math.floor(Math.random()*(max-min))+min
          }
          
      • Number对象

        • MAX_VALUE/MIN_VALUE 仅以Number.调用
        • POSITIVE_INFINITY/NEGATIVE_INFINITY 仅以Number.调用
        • toFixed(位数) 指定小数位数
        • toExponentional(指数) 转换为科学计数法
        • toPercision(精度) 根据精度显示数
      • String对象

        • length

        • charAt(下标) 返回字符(的字符串) charCodeAt(下标) 返回字符的编码

        • concat(string) 返回接好的字符串, 作用同+

        • indexOf(string[, 起始下标])/lastIndexOf(string[, 起始下标]) 从头/尾[或开始下标]开始向后/向前检索子串, 搜到返回第一个匹配串的开始下标,搜不到返回-1;不可以用于正则式

        • search(regex) 功能同上,不可设置起始参数,可用于正则式

        • match(regex) 类似Regex.prototype.exec(str),但会一次性返回所有成功结果,Regex.prototype.lastIndex属性对此函数无效

        • replace("被替换字符串/正则式", "替换字符串"/function (match){return ;})

          • /字符串/i:忽略大小写
          • /字符串/g:匹配所有[详见正则式]
        • localeCompare() 按顺序依次比,对象的字符在前[在字符集中值更小]/一样/后返回-1/0/+1

        • slice/substring([取较小的值作]start, end) 后者忽略负数,当0处理/substr(start[可取负], length)

        • toLowerCase()/toLocaleLowerCase()

        • toUpperCase()/toLocaleUpperCase()

        • trim() 删除字符串两端空白

        • split("字符串中的分隔符(字符串/正则式)"[, 最大成员数]) 将字符串分割为数组

          👉split("")会按字符分隔

      • Date对象

        • 创建 new Date()/new Date(year[两位数会解释为19xx], month, …, milliseconds[👈存储方式&单个参数默认])/new Date(dateString)

        • 显示 default:toString()/toLocalString()短日期+时间/toUTCString() /toDateString()

        • 创建格式

          格式名 格式
          默认输出 星期[3] 月份[3] 日 年[4] 时分秒 时区
          ISO日期 年[4]-月[2]-日T时:分:秒Z/+/-相对时区
          短日期 月[2]/日/年[4] 或 年[4]/月[2]/日
          长日期 月[3或全程] 日[或反过来] 年[4]
        • 获取/设置时间 get/set[UTC]Date/FullYear/Month[始自0的月号]/Day[始自0的星期号]/Hours/Monutes/Seconds/Milliseseconds/ Time()

      • Regex对象

        • var reg=/正则式/修饰符

        • [实例]属性

          • ignoreCase
          • global 用于匹配所有匹配串
          • multiline
          • flags 按字母顺序返回所有修饰符
          • lastIndex 带g修饰符时可指定开始搜索位置,可写,只对一个正则表达式有效
          • source 正则表达式字符串形式
        • [实例]方法

          • test(str) 匹配,能匹配返回true

          • exec(str) 匹配,发现匹配返回匹配成功的子字符串/结果,否则返回null

            • 如果有组匹配/正则式含圆括号,返回[匹配结果,匹配成功组1, ...]

            • 属性:index匹配成功开始位置/inputstr

            var reg=/正则式/g;
            var str='匹配串';
            while(true){
                var match=reg.match(str);
                if(!match) break;
                console.log('#'+match.index+':'+match[0]);
            }
            
        • 匹配规则啊我丢失一半的python笔记啊

          • 字面量字符

          • 元字符

            . 除回车换行分隔符都能匹配

            ^ 字符串开始

            $ 字符串结束

            | 或,自动包含前后的所有字符

            \ 转义符

            [] 字符类

            {} 重复类

            ?={0,1}

            *={0,}

            +={1,}

            () 子组

            ...

          • 转义符 需要匹配与元字符相同的字符,前加\;如果用new RegExp(), 加\\

          • 特殊字符 \n/\r/\t/\v/...

          • 字符类 [字符]匹配一个即可

            • [^字符] 脱字符,除字符之外匹配一个即可,[^]可匹配换行符,但必须在首位
            • [字符-字符] 连字符,在[]间才有效,只读取左右单个字符,也可匹配Unicode
          • 预定义模式/简写

            • \d=[0-9] \D=[^0-9]
            • \w=[A-Za-z0-9] \W=[^A-Za-z0-9]
            • \s=[ \t\r\n\v\f] \S=[^ \t\r\n\v\f]👉/\S\s/可指代一切字符
            • \b=词的边界 \B=非词边界[-两边也算词的边界]
          • 重复类{n}/{n,}/{n,m}

          • 量词符 ?/*/+

          • 贪婪模式[默认]/非贪婪模式[在量词符之后添加?/[+/*/?]?某个模式出现量词符对应的次数时,采用非贪婪模式]

          • 修饰符 g全部匹配/i忽略大小写/m多行[^/$匹配行首行尾]

          • 组匹配

            • 不同时与g修饰符使用,str.match(reg)不捕获分组内容,可配合循环使用reg.exec(str)匹配所有
            • 可使用\n引用第n个组匹配
            • (?:内容) 非捕获组:会进行分组匹配,但不会占用组匹配位置
            • 先行(否定)断言匹配(?=/!会/不会出现的东西)
      • JSON对象

        • 值只能是数组/对象[键名放进"",最后一个成员后不能带逗号]/"字符串"/十进制数/boolean/null
        • 静态方法
          • JSON.stringify(转换对象) 转化为JSON字符串
            • "str"会变成"\"str\""
            • 不符合规范的属性被过滤/数组成员变为null/正则对象变空对象
            • 忽略不可遍历属性
            • 可以有参数2,转为字符串的键[白名单]/处理方法返回值的函数[会处理每个键]
            • 可以有参数3,每个属性前增加的空格数,用于排版
            • 转换对象的toJSON方法[如果有]会覆盖JSON.stringify()方法
          • JSON.parse('JSON字符串', 参数2[同上]) 转化为对应的值
  • 函数/function[Function对象的实例]

    • 不是对象的方法就是全局对象window的函数

    • arguments对象[实参对象]

      • 参数组,有属性length,最多25
      • 即使定义时里没有参数,调用时也可以传参数进此组,可用于重载
      • if写默认参数,否则参数没传够会是undefined
    • Function对象

    • 创建实例

      • 静态方法 function 函数名([args]){pass;}

      • 动态匿名方法/构造器 var 函数名=new Function("参数1", "参数2", ..., "函数语句")[可避免👇]

      • 直接量方法/表达式 [var ]函数名=function ([args]){pass;};

        👉自调用/匿名闭包 函数名=(function (){pass;})();

      • 箭头函数 const 函数名=(args) => {return pass};

      • length 函数期望[定义]的参数个数

      • toString()/valueOf()会返回函数的文本[function...}]

      • call()

        拥有方法的对象.方法.call(调用方法的对象[this], arg1, ...)

      • apply()call()类似,接受数组类型的参数

        拥有方法的对象.方法.call(调用方法的对象[this], [args])

    • 闭包

类型转换

自动转换
  • 运算符&string&number:从左到右,对字符串使用valueOf()/对数字使用toString()

  • valueOf()优先级高于toString()

  • 输出时自动对变量使用toString()

  • 原始值→对应的复杂实例

    • 原始类型调用了属于复杂类型的属性/方法:自动根据前者生成一个复杂类型对象实例“包装对象实例”并显示调用结果
    • 可以使用复杂实例=Object(原始值)实现转换
转换函数
  • 变量.toString([基数])
aNull=null;
aNull.toString();   //会报错
  • parseInt(string[, 基数]) 左至右有一位不是数字即返回,认0/0x,不认./parseFloat(string) 不认0/0x,不认第二个.,没有基数功能
  • 强制类型转换
    • Boolean(value) true: 非0数字/非空字符串/非空对象;false: 0/空字符串/undefined/null

    • Number(value) 整个值可以转换为数字才不返回NaN

      • Number(null)==0

      • Number(new Date(["日期"])) 返回1970/1/1至日期的毫秒数

      • Number(object)==NaN,除非是单值数组。操作:

        var obj={属性: 值};
        Number(obj);  //等同于:
        if (typeof obj.valueOf()==='object'){
            Number(obj.toString());   //[object Object]→NaN
        }
        else{
            Number(obj.valueOf());
        }
        
    • String(value) 什么都能原样转,null也转

类型判断
  • typeof 变量

  • function isDate(变量){
        return 变量.constructor===类型;
        //return 变量.constructor.toString.indexOf("类型")>-1;
    }
    

6 注释

  • 单行//
  • 多行/* */

7 运算符

运算符 意义
=== 等值等型[无需等性运算前转换类型就相等]
!== 不等值/不等型
(condition)?: 三元运算[条件是运算符]
in 是否为(读取?)某对象的属性
instanceof 是否为某对象的实例,等同于对象.prototype.isPrototype0f(实例)
typeof 返回类型,对没有声明过的变量会返回undefined
delete 取消对象的引用,使之成为undefined
void 返回undefined
+/- 可以将字符串转化为数字[并求负]
yield 暂停函数[python: 生成器]
, 常用于变量声明[x,y=y,x应该不行]
>>/>>> 有/无符号右移
&/|/^/~ 位运算与/或/异或/非[EMAScriptAND OR],自动变成32位
&&/| 逻辑运算与/或
</>/== 👉关系/等性运算中,一方为数字,另一方[字符串/boolean]自动转换为数字

8 特殊的值

类型 意义
undefined undefined 只声明未定义的变量值
👉null==undefined
object null 被定义过的空值
number NaN not a number
判断函数: isNaN()
👉NaN与任何关系运算符的运算结果都是false,等号为flase不等号为true
number +/-Infinity 无穷,详见Number对象
判断函数: isFinite()

9 逻辑值转换

输入 输出
undefined false
null false
boolean 结果等于输入的参数(不转换)
number 如果参数为 +0, -0 或 NaN,则结果为false;否则为true
string 如果参数为空字符串,则结果为 false;否则为 true
object true

10 类/对象

  • new操作符

    • 创建一个新的实例对象,赋予此对象当前函数的作用域
    • 将空对象的原型指向构造函数的prototype属性,将空对象赋给函数内部的this关键字
    • 执行构造函数[对象同名函数]
    • 无显示返回对象,则返回此新对象
    • new.target:当前函数以new操作符建立则指向当前函数,否则为undefined
  • this关键字

    • 当前所在的对象[运行环境]

    • 使用方式

      • 全局:this→顶层对象window
      • 构造函数
      • 对象的方法:this当前一层对象/属性/方法
    • 把对象的方法赋给全局变量会让this指向window,需要将对象赋给全局变量再调用方法

    • 多层函数/数组的遍历函数/回调函数中的this会指向全局/全局/DOM对象(本质是函数作为参数的时候会成为全局对象的方法?),需要使用变量[常用that]固定this的值并在内层调用

      //多层函数
      var o={
          f1:function(){
              console.log(this);
              var that=this;
              var f2=function (){
                  console.log(that);
              }();    //函数自调用
          }
      }
      o.f1(); //Object//Object
      //数组遍历
      var o={
          v:'hello',
          p:['a1','a2'],
          f:function f(){
              //1 用that固定this
              var that=this;
              this.p.forEach(function (item){
                  console.log(that.v+' '+item);
              });
              //2 用参数固定运行环境
              this.p.forEach(function(item){
                  console.log(this.v+' '+item);
              },this);
          }
      }
      0.f();
      
    • 在函数中绑定thisFunction.prototype.

      • call([this, default:window])方法

      • apply([this], [args])方法

        • Array.prototype.slice.apply({p:v,length:n})转换类似数组的对象[必须有length]
      • bind()

        • 每次返回一个新的函数,它得到了参数1的环境,但被绑定的方法/函数不用立即执行:函数=拥有方法的对象[default:window].对象的方法[被绑定函数].bind(绑定到的对象[环境], 方法的参数)

        • 也可以用来固定被绑定函数的参数:

          function add(x, y){
              return x+y;
          }
          var puls5=add.bind(null,5); //null/undefined: this→window
          puls5(10);  //15
          
        • 多层函数/数组的遍历函数/回调函数中的this会指向全局/全局/DOM对象,可以在传入函数时增加.bind(需要的环境)

        • 结合call()

          var push=Function.prototype.call.bind(Array.prototype.push);
          //bind:让全局函数push拥有数组的方法
          //call:让
          var a=[1,2,3];
          push(a,4);
          

构造/声明与实例化

  • 工厂方式[实际上发生的事]

    function 方法1(){   //为了让每个实例调用同一个方法[共享成员函数]
      pass;
    }
    function create(arg1, arg2, ...){ //为了创建多个实例、重复调用而设
      var 变量[对象]=new Object();
      变量.attr1=arg1;
      变量.attr2=arg2;
      ...
      变量.方法1=方法1;
      ...
      return 变量
    }
    var 实例1=create(value1, value2, ...)
    var 实例2=create(value1, value2, ...)
    
  • 构造函数方式

    constructor
    function 对象(arg1, arg2, ...){
      this.attr1=arg1;
      this.attr2=arg2;
      ...
      this.方法1=function(){    //不放在外面,依然用不了同一个函数
          pass;
      };
      ...
    }
    var 实例1=new 对象(value1, value2);
    var 实例2=new 对象(value1, value2);
    
  • 原型方式

    prototype
    function 对象(){    //构造函数
    }
    
    对象.prototype.attr1=value1;
    对象.prototype.attr2=value2;
    ...
    对象.prototype.方法1=function(){
        pass;
    };
    ...
    
    var 实例1=new 对象()  //可以使用instanceof检测对象类型
    var 实例2=new 对象()  //问题:不能传值且属性会被共享
    
    • 给本地对象[number/string/...]添加新方法
      Object.prototype.方法=function (){
          pass;
      };
      
    • 重定义已有方法
      Function.proptotype.original方法=Function.prototype.方法
      Function.prototype.方法=funtion (){
          pass;
      }
      
    • 极晚绑定[原本是晚绑定]:先定义实例再增加方法
      var 实例=new Object()
      Object.prototype.方法=function (){
          pass;
      };
      
  • 构造函数/原型方式:属性用构造函数,方法用原型

  • 动态原型方式

    function 对象(arg1, arg2, ...){
        this.attr1=arg1;
        this.sttr2=arg2;
        ...
        if (typeof 对象._initiallized=="undefined"){    //即:加个判断
            对象.prototype.方法1=function(){  //直接量方法
                pass;
            }
            对象.prototype.方法2=function(){
                pass;
            }
            ...
            对象._initiallized=true;
        }
    }
    

继承

  • 对象冒充

    function SubClass(arg1, arg2, ...){
        this.newMethod=SuperClass;    //引用构造函数
        this.newMethod(arg1);     //调用构造函数
        delete this.newMethod;        //取消引用
        
        this.attr2=arg2;
        ...
        this.aMethod=function (){
            pass;
        };
    }
    
  • 使用call()/apply()方法的对象冒充

    function SubClass(arg1, arg2, ...){
        SuperClass.call/apply(this, arg1/new Array(arg1));    //使用构造函数
        this.attr2=arg2;
        ...
        this.aMethod=function (){
            pass;
        };
    };
    
  • 原型链[不支持多重继承]

    function SuperClass(){
    }
    SuperClass.prototype.attr1=value1;
    SuperClass.prototype.method=function (){
        pass;
    };
    function SubClass(){
    }
    
    //SubClass.prototype=new SuperClass();    //需要派生类继承基类所有方法时再用
    SubClass.prototype=Object.create(SuperClass.prototype);   //派生类继承基类原型
    SubClass.prototype.constructor=SubClass;  //指定构造函数
    
  • 混合方式:属性用对象冒充,方法用原型链

  • 多重继承

    function M1(){        //Mixin混入
        this.attr1=value1;
    }
    function M2(){
        this.attr2=value2;
    }
    function SbuClass(){
        M1.call(this);
        M2.call(this);    //对象冒充方法
    }
    
    SubClass.prototype=Object.create(M1.prototype);
    Object.assign(SubClass.prototype,M2.prototype);
    
    SubClass.prototype.constructor=SubClass;
    var s=new SubClass();
    

模块

  • 定义:一组封装好的属性和方法,实现特定功能

  • 写成对象:可能被改👇

  • 封装私有对象

    • 构造函数:同时存塑造和保存实例,违背构造函数设计目的,且耗内存×

    • 立即执行函数:基本写法

      var module=(function (){
          var _count=0;
          var m1=function (){
              //...
          };
          var m2=function (){
              //...
          };
          return {
              m1:m1,
              m2:m2
          };
      })();   //自调用函数
      
      • 模块放大

        var module1=(function (mod){
            mod.m3=function (){
                //...
            };
            return mod;
        })(module1);
        //宽放大模式
        })(window.module1||{})
        
      • 输入库/全局变量-命名空间

        var module=(function ($,window,document){
            function initialize(){
                //...
            }
            function dieCarouselDie(){
                //...
            }
            //...
            window.finalCarousel={
                init:initialize,
                destroy:dieCarouselDie    //外部可调用的只有这两个属性
            }
        })(jQuery,window,document)
        

11 事件

  • 事件的传播

    • 阶段
      • 捕获:window→目标节点
      • 目标:事件触发[最深的触发节点默认为目标节点,event.eventPhase覆盖为target]
      • 冒泡:目标节点→window
    • 事件的代理delegation:在父节点上添加监听函数,同时处理子节点的事件
      • 阻止传播但不取消监听函数:event.stopProgagation()
      • 阻止两者:event.stopImmediatePropagation()
  • [过时了]HTML事件 <element envent="代码">GlobalEventHandlers接口,由HTML元素/document对象/Window对象继承

    • onchange/onfocus/onblur/onselect/onsubmit
    • onclick/ondblclick/onmouseover/onmouuseout/onmousemove
    • onkeypress/onkeydown/onkeyup
    • onload/onunload/onreset/onerror[js错误:message/source/lineno /colno/error/资源加载错误]/onabort/onresize
    • document.oncontextmenu=funtion (){return false;}
    • <dialog>:oncancel/close
  • DOM事件操作接口:element.on事件=监听函数 重复定义会覆盖

    👆 以上两者皆只在冒泡阶段被触发

  • EventTarget接口

    • addEventListener('type', listener监听函数[, useCapture-t捕获[←默认]f冒泡])
      • type 事件类型
      • listener 监听函数,有handleEvent方法的对象也可以
      • useCapture/{capture, once, passive}
      • 添加多个监听函数,按添加顺序执行;自动跳过重复的监听函数
      • 可以使用匿名闭包往监听函数装参数:function (event){listener(para);}
      • event 当前事件 this 当前事件所在的对象
    • removeEventListener('type', listener, false) 必须在同一元素节点上移除用👆添加的同名监听函数,第三个参数也相同
    • dispatchEvent(event) 在当前节点触发Event对象,返回是否调用preventDefault[是否存在?]
  • Event对象

    • var event=new Event('type', options{'bubbles','cancelable'})
    • 属性
      • bubbles 是否冒泡[默认不冒]
      • eventPhase 0没发生/1捕获/2到达节点/4冒泡
      • cancelable 是否可以取消[Event对象构造的默认不行]/preventDefault 能取消就取消/cancelBubble 阻止传播/defaultPrevented 是否调用过👆
      • target 原始触发节点/currentTarget 正在通过的节点
      • type
      • timeStamp 毫秒值,事件发生时间
      • isTrue 是否为用户产生[否:脚本写的]
      • detail 用户界面事件具有,取决于具体事件
    • 方法
      • preventDefault() 取消浏览器的默认事件,但不阻止事件传播
      • stopPropagation()
      • sropImmediatePropagation() 阻止元素上的剩余事件监听函数被执行
      • composedPath() 触发节点及冒泡经过的所有上层节点组成的数组
  • 各种事件:

    • 鼠标mouseenter/leave不在进入/离开子节点中重复触发/mouseover/out
    • 键盘:按着不放keydownkeypress交替出现/code按下的键/key按下的特殊字符
    • 进度ajax请求也可以添加事件监听函数
    • 表单submit事件/InputEvent对象:data/inputType/dataTransfer
    • 触摸:触屏中默认同时触发鼠标事件/screen/client/pageX/Y相对于屏幕/浏览器/当前页面/radiusX/Y/rotationAngle:精确描述触摸/TouchEvent.touches/changedTouches/targetTouchesTouchList/ touchstart/end/move/cancel/target
    • 拖拉
      • drag/drop[ondrag=event.preventDefault()]
      • DragEvent接口:多重继承自Event接口和MouseEvent接口
      • DataTransfer接口
        • 属性
          • dropEffectcopy/move/link/none 一般在dragenter/over的监听函数中设置
          • effectAllowed
          • files:接收拖拉文件,详见test_file.html&js
          • types:拖拉的数据格式,MIME值,text/plain/text/html/text/uri-list/image/jpeg/...
          • items:返回DataTransferItemList实例[length/ add(data,type)/add(file)/remove(index)/clear()/]→DataTransferItem实例[kind[string/file]/type/getAsFile() /getAsString(callBack)]
        • 方法
          • setData('type','data'):可再来一份纯文本
          • getData('type')
          • clearData('type')[无法移除拖拉文件]
          • setDragImage(img节点,鼠标相对于图片左上角的x,y)
    • 资源/session/网页状态/窗口/剪贴板/焦点/CustomEvent
      • beforeunload/unload/load[加载缓存时不触发]/error/abort
      • session:历史事件
        • 缓存:pageshow[第一次加载/缓存加载都触发]/persisted:是否为缓存/pagehide离开当前页面,页面内容会保存在缓存中/persisted:是否保存→否:此后执行unload监听函数→只在history对象发生变化时触发
        • popstate事件:history对象显示切换:鼠标/history.back/forward/go()/属性:state
        • hashchange:URL中#及以后部分改变→不重新加载页面但会产生新的历史记录→前端!router!/属性:oldURL/newURL
      • DOMContentLoaded[资源可能还没加载完]/readystatechangeDOM/AJAX/ loading/interactive/complete
      • scroll:throttle详见test_file.js/resize/fullscreenchange/ error
      • event[ClipboardEvent实例:cut/copy/paste]. clipboardData[DataTransfer实例]
      • event[FocusEvent实例:focus/blur[只捕获:addEL:t]/focusin/out]. target/relatedTarget[前2:null/后2:节点]
      • CustomEvent接口:用于在触发事件时传入数据:new CustomEvent('type',options:{'detail':'数据'})

12 条件/循环

类似C

  • if () else if else
  • switch() case[不同情况共享代码:上下各一行] default
    • 比较使用===,不发生类型转换
    • 最好使用对象结构代替
  • while()/do{}while(); 先判断后执行/先执行后判断
  • for (;;)
  • for (属性 in 对象) 依次返回对象的可枚举属性
  • break 跳出循环/continue 跳过/终止本轮,开始下一轮循环
  • 标签label 标记位置,可示意break/continue语句跳到哪里,可跳出任何代码块

13 错误

  • Error对象:var err=new Error(meaasage[, name, stack]);
  • 原生错误:SyntaxError语法错误/ReferenceError引用错误(对象不存在/无法被赋值)/RangeError/TypeError(new了原始对象/调用不存在的方法)/URLError 可套用👆
  • throw 任何值→程序终止
  • try{} catch(){} [finally{}] catch跑完/出现throw/returnfinally→终端执行[并return returnthrow会互相覆盖]

14 控制台用法

  • console.log/info[/debug]()
    • 占位符基本同C+%o对象的连接+%cCSS格式字符串
    • 输出一个对象,会显示构造函数
  • console.wran/error()
  • console.table() 以表格显示复合类型数据
  • console.count([para]) 统计自己被调用的次数:para: count
  • console.dir/dirxml(obj) 对象检查
    • console.dir(DOM对象) 显示DOM对象的所有属性
    • console.dirxml(DOM对象) 以目录树显示DOM节点
  • console.assert(条件, 错误信息) 条件==false时,提示错误信息但不中断程序
  • console.time&timeEnd()
  • console.group/groupCollapsed/groupEnd()
  • conosole.tace() 返回代码在堆栈中的调用路径/console.clear() 清除控制台所有输出
  • 之后学:命令行API
  • debugger; 存在除错工具则自动停下,自动打开源码页面

14 严格模式

  • 'use strict'
    • 放在脚本第一行
    • 合并是与不是严格模式的脚本,可以将严格模式的放进匿名闭包/自调用/立即执行的匿名函数
  • 报错无效操作
    • 更改了只读属性/删除了不可配置属性
    • 只给属性设置getter
    • 尝试更改对象被冻结的部分
    • eval/arguments作为标识名
    • 函数出现重名参数
    • 使用0前缀标识八进制数
  • 报错不安全操作
    • 不显式声明全局变量
    • 函数内部的this指向了window而非它所在的对象(并且this指向null/undefined时,不会自动把this指向window
    • 删除除了对象的可删除属性的变量
  • 限制动态绑定
    • 不能使用with
    • eval()中为独立的作用域
    • 除了调用函数,无法改变arguments数组

15 性能优化

16 异步操作

  • 单线程

  • 同步/异步任务

    • 同步

    • 异步[挂起]←循环检查机制:事件循环👉类似操作系统检查I/O操作

      • 操作模式

        • 回调函数[必须要有]:在函数1结尾时调用函数2,保证运行顺序
        • 事件监听:
          • function f1(){...f1.trigger('事件')}&f1.on('事件',f2)
          • 去耦合[coupling]但运行流程不清晰
        • 发布/订阅模式/观察者模式(有PV操作内味了)
        jQuery.subcribe('事件',f2);
        function f1(){
            //...
            jQuery.publish('事件');
            //...
        }
        jQuery.unsubcribe('事件',f2);
        
      • 流程控制

        • 串行:做个数组放return里递归着删
        • 并行:做个数组forEach()
        • 结合:规定最高并行数量:函数套在lquncher()里,设置running<limit才在函数中调用launcher()
      • AJAXAsynchronous Javascript And XML(可扩展标记语言)[也可能用纯文本或者JSON传数据],详见BOM

        • 事件→js创建XMLHttpRequest对象→对象对服务器发送请求→服务器处理并响应→js读取→js更新页面等
        • 请求
  • 定时器

    • setTimeut(函数[回调函数]/'代码', 延迟执行毫秒数[default=0][, 回调函数的参数]) 返回定时器编号[可用于取消],定时器编号自动递增

      $('textarea').on('keydown',debounce(ajaxAction,2000))//"防抖"
      function debounce(fn,delay){
          var timer=null;
          return function(){
              var context=this;
              var args=arguments;
              clearTimeout(timer);
              timer=setTimeout(function (){
                  fn.apply(context,args);
              },delay);
          };
      }
      
    • setInterval() 用法同上,间断(毫秒数-运行时间)无限次执行

    • clearTimeout/clearInterval(定时器编号)

    • 会被事件循环的延迟(sleep(n)等)干扰,此后在等待后继续生效

    • setTimeout(f,0)

      • 在同步任务结束后进入事件循环,即在下一事件循环的开始执行
      • 应用
        • 使子元素的回调函数成为setTimeout()中的函数,使子元素回调函数不会自动先于父元素回调函数触发
        • 把浏览器同步任务做完再干的事放进setTimeout()
        • 把耗时的js操作放进setTimeout()里递归
  • Promise对象

    • var p1=new Promise(f1); p1.then(f2);
    • 目的:改善f2作为回调函数写在f1里作为回调函数时古怪的代码
    • 状态
      • pendingfulfilledPromise实例传回revolve👇中的值
      • pendingrejectedPromise实例抛出reject👇中的错误
    • 构造函数
      • resolve(value)fulfilled
      • reject(new Error())rejected
    • 实例方法
      • then(成功时的回调函数, 失败时的回调函数) 返回一个Promise对象,支持写一串
      • 调用then()Promise对象的返回值/前一个then()中回调函数的返回值(Promise对象)的返回值,会成为后一个then()中的回调函数的参数
    • 微任务:追加到本轮事件循环,早于异步任务

17 HTML DOM/文档对象模型

  • 定义

    • HTML的标准对象模型和编程接口/获取/添加/更改/删除HTML元素的标准
    • HTML元素作为对象/访问它的属性/方法/事件
    • 浏览器根据DOM模型将HTML之类的结构化文档解析、组成DOM
  • 节点/接口

    • DOM的最小组成单位,继承自节点对象Node

    • var node=节点: 引用

      • 常量:9DOCUMENT_NODE/1ELEMENT_NODE/2ATTRIBUTE_NODE/3TEXT_NODE/11DOCUMENT_FRAGMENT_NODE/10DOCUMENT_TYPE_NODE/8COMMENT_NODE
      • 属性
        • nodeType 👆常量之一
        • nodeName 根据节点返回#document/大写标签名/属性名/#text/#document-fragment/文档类型/#comment
        • nodeValue Text/Comment/Attr对应其文本值,其它结果为null
        • textContent 忽略所有HTML标签识别,读/写所有文本内容
        • baseURI 绝对路径
        • ownerDocument 顶层文档对象,不可用于文档节点
        • next/previousSibling/parentNode/Element/first/lastChild/childNodes
        • isConnected 节点是否在文档中
      • 实例方法
        • append/removeChild(Node)
        • replaceChild(newNode, oldChild)
        • hasChildNode(Node)
        • cloneNode(true)[会缺被克隆节点的事件回调函数/克隆完需要被添加]
        • insertBefore(Node[插在→之前, refeNode/null:插最后])
        • contains(Node) Node为调用节点/的子/后代节点/compareDocumentPosition(Node) Node在调用节点的相同节点/不同文档/前面/后面/包含/被包含/浏览器内部:返回0/1/2/4/8/16/32,多种情况并存则相加;使用时需要进行位运算
        • isEqual/SameNode() 类型属性子节点是否相同/是否为同一节点
        • normalize() 处理当前节点的所有文本子节点,空的删除相邻的合并
        • getRootNode() 可用于文档节点
    • 节点组:接受DOM属性返回的节点集合

      • NodeList:各类都可以有
        • 来自:Node.childeNodes()[会返回动态集合,DOM改变则随之改变]/document.querySlectorAll()[返回静态集合]等方法
        • 可以用var nodeArr=Array.prototype.slice.call(NodeList)转换为数组
        • 属性:length
        • 实例方法
          • forEach()
          • item()/下标
          • keys()/values()/entries()
      • HTMLCollection:只能有element节点
        • length
        • item()
        • namedItem('id/name的值') 返回id/name值同参数的节点
    • Parent/ChildNode

      • ParentNode:拥有子节点的节点
        • 可能有子节点的节点:element/document/documentFragment
        • children
        • childElementCount
        • first/lastElementChilren
        • append/prepend()
        • normalize() 合并Text节点
      • ChildNode:拥有父节点的节点
        • remove()
        • before/after(Node) 在当前结点之前/之后插入参数节点
        • replaceWith()
    • 文档document 顶层节点/手册

      • 获取
        • [window.]document
        • iframe框架网页的iframe.contentDocument
        • XMLHttpRequest.responseXML
        • {innerNode}.ownerDocument
      • 属性
        • 快捷方式
        • 节点集合:HTML对象选择器 标签同名s[下标/'id'/'name'] 返回HTMLCollection
        • 文档静态信息:[document]URL/doman/location/...
        • 文档状态:hidden/visibilityState/readyState[loading→interactive→complete]
        • cookie
        • designMode可编辑:on/off
        • currentScript
        • implementation.createDocument()/HTMLDocument()/DocumentType()
      • 实例方法
        • open()/close()
        • write('HTML代码')/writeIn()
        • 查找HTML元素 getElementById('id')/getElementsByName('name')/getElementsByClassName('name1 name2 ...')/getElementByTagName('tag')
        • CSS对象选择器 querySelector/querySelectorAll('CSS选择器') 但无法选择伪元素和伪类
        • 添加/删除
          • remove/append/replaceChild('element')
          • adoptNode(externalNode)/importNode(externalNode, deep?) 只改变了归属,还需要用👆插进文档树
          • createElement('element')/createTextNode()[不转义双引号]/createAttribute/Comment /DocumentFragment()
          • create/dispatchEvent('type{UI/Mouse/...Event}')/add/removeEventListener
        • 遍历
          • createNodeIterator(root, NodeFilter.type)
            • type: SHOW_ALL/ELEMENT/TEXT/COMMENT
            • 返回NodeFilter实例→.next/previousNode()遍历并返回?所在节点后指向下一个/指向上一个后返回
          • createTreeWalker(root, NodeFilter.type) 返回TreeWalker实例
        • element[s]FromPoint(x, y)
        • hasFocus()
        • query: execCommand('bold/createLink/delete/italic/insertHTML/...', false[recommended], input[辅助内容?])/queryCommandSupported ('exex命令')/queryCommandEnabled()
    • DocumentType

    • Element HTML标签/元素

      • 改变 innerHTML/[attribute]/setAttribute(attr,value)/style.[property]

      • 属性

        • **属性相关 **

          • id/tagName/dir/accessKey[转移focus快捷键]/draggable/ lang/tabIndex[规定Tab键遍历时的顺序]/title[鼠标悬浮提示框]/...
          • [attribute] forhtmlFor classclassName
          • attributes[.属性名/['属性名]'/[下标]]拥有namevalue属性
          • 自定义属性data-*[不能有大写可改用-] dataset.[data-后的内容] 读取data-开头的属性,在JS中用驼峰写法,HTML中用-连接
        • 状态相关 hidden[CSSs的display设定高于👈]/isC/contentEditable

        • className返回以空格分隔的字符串/classList返回类似数组的对象

          classList.add/remove/contains/toggle不存在则加入存在则移除('class')/item(下标)/toString()

        • outerHTML包括标签的HTML代码 无父节点会报错/innerHTML/ textContent

        • style[.property]

        • clientHeight/Weight 包括padding块级元素高/宽[body网页/documentElement视窗]/clientLeft/Top左/上border宽度

        • scrollHeight/Weight 适用所有元素,包括padding/伪元素/scrollLeft/Top滚动条宽/高

        • offsetParent 返回最靠近当前元素,忽略display: noneposition: fixed的那些/offsetHeight/Weight 包括整个盒子和滚动条/offsetLeft/Top 当前元素左上角相对于offsetPerent的水平/垂直位移

        • children/childElementCount 只包括元素类型子节点

        • first/lastElementChild/next/previousElementSibling

      • 实例方法

        • 属性相关 get/set/has/removeAttribute()/getAttributNames() /hasAttributes()

        • CSS选择器 querySelector('选择器1, 选择器2, ...') 全局搜索选择器/querySelectorAll()/closest('选择器') 离选择器最近的符合要求的当前或祖先节点/matches('选择器')

        • 元素节点下搜索 getElementsByClass/TagName

        • 事件相关→EventTarget接口

          • 添加/删除事件监听器 add/removeEvenListener('事件', 处理函数,false)
          • dispatchEvent(Event对象)
          • 添加事件处理程序 事件=funcion (){//...}
        • scrollIntoView([default:true/false]) 元素与当前可见区域顶部/底部对齐[用于置顶导航栏?]

        • getBoundingClientRect() 返回rect对象,包含CSS盒子信息,属性皆来自继承:x/y元素左上角相对于视口/height/width.left/right/ top/bottom/绝对👉window.scrollX/Y+left/top

          getClientRects() 对内联元素返回行数,会考虑被HTML忽略的换行

        • insertAdjacentElement(position{before[当前结点之前,需要父节点]/afterbegin[内部第一个子节点之前]/before/afterend}, element)

          insertAdjacentHTML/Text(position, text) 不转义,不可用于处理用户输入内容

        • remove()/focus/blur()/click()

    • Attribute

    • Text[对象]

      • 属性 data[=nodeValue]/wholeText/其它同Node
      • 方法
        • appendData('str')/deleteData(位置, 子串长度)/insertData(位置, 'str')/replaceData(位置, 长度, 'str')/subStringData(位置, 长度)
        • splitText(位置) 分割位置后方的字符串为新节点
        • 其它同Node
    • Comment

    • DocumentFragment 不属于文档、可灵活使用的DOM对象

      • Node多了:children/first/lastElementChild/childElementCount
  • 节点树

    节点树
  • 表单

    • 约束验证DOM:document.getElementById('id')<input>
      • checkValidity()/setCustomValidity()
      • validity/validationMessage/willValidate
  • CSS操作

    • get.set/removeAttribute()方法更改style属性
    • CSSStyleDeclaration接口/对象:Element.style/CSSStyle.style/window.getComputedStyle()最终样式信息可调用
      • 返回绝对单位[px/#rgb值]/简写[margin/font等]无效/styleObj['a-b']/ styleObj.aB
      • .CSS属性 需要改成驼峰写法/.cssText='str'+... 不需要改写
      • length 返回样式声明数量
      • parentRule 返回CSSRule实例[如果有]
      • getPropertyPriority('属性名') 设置important优先级则返回
      • getPropertyValue('属性名')
      • item(下标)
      • removeProperty('属性名')/setProperty('属性名'[, 'value', 'important'])
    • 模块侦测:HTML元素.style['属性名[-/驼峰写法皆可]'] 浏览器支持返回string/不支持返回undefined/浏览器的CSS前缀:mos/webkit/o/ms/khtml
    • CSS对象
      • CSS.escape(含有需要转义的特殊字符的值)
      • CSS.supports('属性','值'/'CSS语句[不带分号]')
    • StyleSheet接口/对象,可以[下标]读取
      • document.styleSheets/elem.sheet返回此对象
      • 属性 disabled[只能在js代码里设置]/href/media:screen/print/ all/title/type:text/css/parentStyleSheet/cssRules.items(下标)/[下标][.cssText/style.property='value']/通过@import/加载输入的样式表:ownerNode:link/style/ownerRule
      • 实例方法
        • insertRule('CSS语句', 插入位置[=0]) 最好放进try/catch
        • deleteRule(语句位置)
    • CSSRuleList接口/对象
      • sheet.cssRules得到
      • CSSRule接口/对象
        • 属性
          • cssText
          • parentStyleSheet 返回所属的StyleSheet对象
          • parentRule 返回父规则
          • type 普通/CSSStyleRule/@import/@media[可用于区分电脑/手机屏幕]/CSSMediaRule/@font-face
            • CSSStyleRule接口/对象: 属性 selectorText/style
            • CSSMediaRule接口/对象: 属性 media 返回MediaList实例/conditionText
    • windows.matchMedia('MediaQuery条件语句: mediatype and/or/only (feature)') 返回MediaQueryList实例
      • 属性
        • media 返回条件语句
        • matches 返回是否符合条件
        • onchange=监听函数function(MediaQueryListEvent实例){//...}
      • 实例方法 add.removeListener(监听函数)
  • 监听DOM: Mutation Observer API

    • 不是同步触发的事件[不是指事件循环],是异步,以MutationRecord数组记录所有DOM操作,全部结束/任务队列清空后触发

    • var observer=new MutationObserver(回调函数:function (变动数组, observer){//...});

    • 实例方法

      • observe(DOM节点/target, 变动) 启动观察器
        • 变动:一个对象,至少有一下一个键值对
          • 键:childList观察子节点/attributes观察属性/ characterData观察内容/文本/subtree是否观察节点所有后代/attribute/characterOldV alue/attributeFilter指定观察属性的数组
          • 值:功能是否开启
        • 对同一个节点做多个变动观察,观察器相同则无效,不同则覆盖
      • disconnect()停止观察/takeRecords()停止观察并返回未处理变动数组
    • MutationRecord对象

      • 属性:type/target/add/removeNodes/previous/nextSibling /attributeName/oldValue[只对attribute/characterData有效]
    • 封装的DOM观察函数

      (function(win){
        'use strict';
      
        var listeners = [];
        var doc = win.document;
        var MutationObserver = win.MutationObserver || win.WebKitMutationObserver;
        var observer;
      
        function ready(selector, fn){
          // 储存选择器和回调函数
          listeners.push({
            selector: selector,
            fn: fn
          });
          if(!observer){
            // 监听document变化
            observer = new MutationObserver(check);
            observer.observe(doc.documentElement, {
              childList: true,
              subtree: true
            });
          }
          // 检查该节点是否已经在DOM中
          check();
        }
      
        function check(){
        // 检查是否匹配已储存的节点
          for(var i = 0; i < listeners.length; i++){
            var listener = listeners[i];
            // 检查指定节点是否有匹配
            var elements = doc.querySelectorAll(listener.selector);
            for(var j = 0; j < elements.length; j++){
              var element = elements[j];
              // 确保回调函数只会对该元素调用一次
              if(!element.ready){
                element.ready = true;
                // 对该节点调用回调函数
                listener.fn.call(element, element);
              }
            }
          }
        }
      
        // 对外暴露ready
        win.ready = ready;
      
      })(this);
      
      // 使用方法
      ready('.foo', function(element){
        // ...
      });
      

18 BOM

  • 浏览器环境

    • JS嵌入:<script>/URL协议:<a href="javascript:语句1;语句2;..."></a>
    • <script>
      • 将之放在页面底部,防止假死,防止调用没有生成的DOM
      • 脚本运行顺序根据标签出现先后决定
      • defer:不可用于内置脚本和动态生成的script标签,加入后,脚本在DOMContentLoaded事件出发前/读取完</html>标签后执行
      • async:加入后,在遇到此标签时开启另一个进程下载脚本,下载完了就执行,无法以标签顺序保证先后,会覆盖defer的作用
      • 动态加载:['a.js','b.js].forEach(//...)详见loadScript.js
      • 加载协议:默认HTTP:src='a.js'/指定:src='http://a.js'/根据页面本身决定:src='//a.js'
  • 浏览器组成

    • 渲染引擎:Webkit/...
      • HTMLDOM&CSSCSSOM/render tree/layout/flow&paint
      • 优化:减少重流重绘次数
        • DOM一起写
        • 缓存DOM
        • CSSclass一次性改样式
        • 使用虚拟DOM
        • 使用absolute/fixed定位动画
        • [?]用documentFragment操作DOM
        • [?]用window.requestAnimationFrame(function ...)容纳DOM操作
    • JS解释器/引擎:V8/...
      • 即时编译JIT:代码编译为字节码并缓存,运行时只编译用到的语句,并且编完了缓存
  • window对象

    • 属性

      • name 浏览器窗口名,只要不关都会被记忆
      • closed 一般用于检查window.open()制造的弹窗是否被关闭/opener 一般用于切断与父窗口[打开窗口的窗口]的联系,防止被父窗口URL被修改
      • window.self/window===true
      • frames 返回页面中所有窗口:<frame>/<iframe>/lendth 返回页面中窗口的个数/[?]frameElement
      • top/parent 获取顶层/父窗口
      • status 状态栏文本[不被支持]
      • devicePixelRatio:物理像素CSS像素比,越大越高清
      • isSecureContext是否为加密环境/用了HTTP协议
      • screenX/Y/innerHeight/Width窗口可见部分高宽,包括滚动条/outerHeight/Width浏览器窗口高宽/scrollX/Y/pageX/YOffset浮点数,水平/垂直滚动距离
      • locationbar地址栏/menubar菜单栏/scrollbars/toolbar/statusbar /personalbar
      • 全局对象属性document/location:URL/navigator:环境/history:浏览历史/local/sessionStorage/console/screen
    • 方法

      • alert('strMsg')/var result=window.prompt('strMsg'[,默认输入]):用户输入/默认值/null/var result=window.confirm('strMsg')true/false

      • var popup=window.open('url','windowName'[,windowFeatures]) 返回新窗口的引用/popup.close() 关闭open()制造的窗口/stop() 停止加载资源

      • moveTo/By(x,y) 移动open()创建且只有一个标签页的窗口到某位置/移动某距离

      • resizeTo/By(x,y) 缩放绝对/相对大小

      • scroll[To](x,y)/(options:{top=y,left=x,behavior:smooth, instant,auto[default]})/scrollBy(x,y)/element.scrollTop/Left/IntoView()

      • print()if(tyepof window.print==='function'){//...}

      • window(实例).focus/blur()

      • getSelection()读取被选中的文本

      • requestAnimationFrame(callback{performance.now()距离网页上次加载的时间}) 在浏览器下一次重流时执行回调函数并重绘[间隔16ms],返回一个整数,可以用cancelAnimationFrame()取消

        var element=document.getElementById('animate');
        element.style.position='absolute';
        
        var start=null;
        function step(timestamp){
            if (!start) start=timestamp;
            var progress=timestamp-start;
            element.style.left=Math.min(progress/10,200)+'px';
            if(progress<2000){
                window.requestAnimationFrame(step);
            }
        }
        //视觉效果很平滑同时没有造成过多的重绘
        window.requestAnimationFrame(step);
        
      • reqyestIdleCallback(callback{IdleDeadline:{didTimeout& timeRemaining()}}[,options:{timeout最长推迟毫秒数}]) 等系统资源空闲时执行回调函数,返回一个整数,可以用cancelIdleCallback()取消

    • 事件

    • 窗口

      • top/parent/self
      • frame.contentWindow.document/contentDocument/frameElement
      • window.frames[i]/id.document
  • navigater对象

    • 环境信息:浏览器+系统
    • 属性
      • userAgent浏览器/plugins插件/platform操作系统
      • online/offline
      • language[s]/languagechange
      • getCurrentPosition()/watchPosition()/clearWatch()
      • cookieEnable浏览器是否能用cookie
    • 方法
      • javaEnabled()是否能运行Java Applet小程序
      • sendBeacon()异步发数据
  • screen对象

    • 显示设备信息

    • 属性:height/wodth/availHeight/Width/pixel/colorDepth/

      orientation屏幕方向:type:landscape/portrait横竖-primary/secondary正倒

  • cookie

    • 保存状态信息:session管理/个性化/追踪用户分析行为
    • 元数据:名字/值[信息]/到期时间/所属域名/生效路径
    • 服务端要求浏览器保存cookieHTTP头信息中添加:Set-Cookie:<cookie-name>=<cookie-value>;属性=<value>,一个一行
      • 修改:key/domain/path/secure都匹配
      • 否则生成新cookie,最匹配的排前面
    • 浏览器发送:HTTP头信息中添加:Cookie:<cookie-name1>=<cookie-value1>;...[不知道属性和设置它的域名]
    • 属性
      • Max-Age=存在秒数/Expires=作废时间(Date.prototype.toUTCString())
        • Max-Age优先
        • 都不设置/写成null:浏览器关了就删Session Cookie
      • Domain=附带cookie的域名/默认当前不带子域名/Path=附带cookie的路径/只要当前路径的一部分有它就附带
      • Secure 用HTTP协议[加密]才发cookie/HttpOnly 只有发HTTP请求时服务器才拿到cookie/document.cookie/XMLHttpRequest/Request API都不行
      • 限制第三方cookieSamSite
        • 滥用:CRSF攻击[防止:发随机token]/用户追踪
        • Strict跨域则不发cookie
        • Lax链接/预加载/GET表单发
        • NoneSet-Cookie:name=value;SamSite=None;Secure
    • document.cookie
      • 读:返回当前网页没有HttpOnlycookie组成的数组
      • 写:path绝对路径/domain一级域名/max-age/expires
      • 删除:把expires设成过去日期
    • XMLHttpRequest对象/ajax
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容