方便起见不分parameter[形参,出现在函数定义中]和argument[实参,其值为传入函数的值],一律当作argument记录
javascript
会在上下行无法合并解释时自动添加行末封号,++
和--
加在前面,{}当与语句同行
1 改变元素内容:点击显示日期时间
- 访问元素:
document.getElementById('ID')
2 改变属性
- 隐藏/显示元素
3 外置脚本
或
- 放在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/+1slice/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
匹配成功开始位置/input
:str
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();
-
在函数中绑定
this
:Function.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, ...)
-
构造函数方式
function 对象(arg1, arg2, ...){ this.attr1=arg1; this.attr2=arg2; ... this.方法1=function(){ //不放在外面,依然用不了同一个函数 pass; }; ... } var 实例1=new 对象(value1, value2); var 实例2=new 对象(value1, value2);
-
原型方式
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; };
- 给本地对象[number/string/...]添加新方法
构造函数/原型方式:属性用构造函数,方法用原型
-
动态原型方式
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事件
→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;}
-
-
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
会 - 键盘:按着不放
keydown
与keypress
交替出现/code
按下的键/key
按下的特殊字符 - 进度:
ajax
请求也可以添加事件监听函数 - 表单:
submit
事件/InputEvent
对象:data
/inputType
/dataTransfer
- 触摸:触屏中默认同时触发鼠标事件/
screen/client/pageX/Y
相对于屏幕/浏览器/当前页面/radiusX/Y
/rotationAngle
:精确描述触摸/TouchEvent.touches/changedTouches/targetTouches
→TouchList
/touchstart/end/move/cancel/target
- 拖拉
drag/drop[ondrag=event.preventDefault()]
-
DragEvent
接口:多重继承自Event
接口和MouseEvent
接口 -
DataTransfer
接口- 属性
-
dropEffect
:copy/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[资源可能还没加载完]
/readystatechange
:DOM/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
/return
→finally
→终端执行[并return
return
和throw
会互相覆盖]
14 控制台用法
-
console.log/info[/debug]()
- 占位符基本同C+
%o
对象的连接+%c
CSS格式字符串 - 输出一个对象,会显示构造函数
- 占位符基本同C+
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 性能优化
javascript
性能
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
才在函数中调用 launcher()
- 串行:做个数组放
-
AJAX
:Asynchronous 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
里作为回调函数时古怪的代码 - 状态
-
pending
→fulfilled
:Promise
实例传回revolve
中的值 -
pending
→rejected
:Promise
实例抛出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=节点
: 引用
- 常量:9
DOCUMENT_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]
for
→htmlFor
class
→className
-
attributes[.属性名/['属性名]'/[下标]]
拥有name
和value
属性
- 自定义属性
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: none
和position: 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')
为
-
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