导图社区 JavaScript思维导图
这是一篇关于深入学习计算机的思维导图。该思维导图为我们总结了关于这一部分的非常重要的知识点,干货满满,不要错过哦。
编辑于2021-09-10 18:35:16JavaScript
start at 2021.3.8
orirgin&characteristics
liveScript
validation of web pages,前端验证
ES标准
ECMAScript
JS实现
JSengine
Chrome V8 engine
JavaScript
ECMAScript
标准
DOM
操作网页
BOM
操作浏览器
解释性语言
面向对象
JS编写位置
<!DOCTYPE html> <html> <head> <title>JS编写位置</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="keywords" content="VEZZZING'S BILDINGS"> <meta name="description" content="StartAt2021.3.8"> <meta name="author" content="VEZZZING"> <!--写到script标签,省略--> <!--引用外部JS文件,也通过script标签, 不过这个script标签不能再编写代码了--> <script type="text/javascript" src="JS/jsPosition.js"></script> </head> <body> <!--结构与行为耦合,不方便调试--> <!--到按钮点击事件--> <button onclick="alert('被点击~~');">点我一下</button> <!--到超链接--> <a href="javascript:alert('pressed');">点这里</a> </body> </html>
内嵌
外部导入
事件中
基本语法
<!DOCTYPE html> <html> <head> <title>JS编写位置</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="keywords" content="VEZZZING'S BILDINGS"> <meta name="description" content="StartAt2021.3.8"> <meta name="author" content="VEZZZING"> <!--注释同Java--> <script type="text/javascript"> /* */ // </script> <script type="text/javascript" src="JS/jsPosition.js"></script> </head> <body> <!--结构与行为耦合,不方便调试--> <!--到按钮点击事件--> <button onclick="alert('被点击~~');">点我一下</button> <!--到超链接--> <a href="javascript:alert('pressed');">点这里</a> </body> </html>
声明多个变量
var a=1,b=2,c=3;
变量与字面量
标识符
标志符[identifier]
JS中所有的自己定义的量
JS保存变量名用UTF-8
命名规范
可以含有字母数字_$
不能以数字开头
不能与关键字保留字重名
驼峰命名
变量的声明
var a; a=123; console.log(a);
var b=789;
数据类型
type
基本数据类型
String
单双引号一样
字符转义
\t
\n
\'单引号
\"表示双引号
\\
Number
一些字面量
Number.MAX_VALUE
输出JS中可承受的最大值
Number.MIN_VALUE
5e-324
如果超过最大值,则返回Infinity字面量
console.log(typeof Infinity);->number
不可运算则返回NaN[not a number]
console.log(typeof NaN);->number
计算
整数基本正确
浮点数会不精准
进制
var a; a=0x10; console.log(a); ->16
十六进制0x
八进制0
二进制0b【浏览器兼容性较差】
a=parseInt(a,10);指定转换成的进制
Boolean
Null
var a=null;
表示为空的对象
console.log(typeof a);->object
Undefined
未定义
声明变量但还没有赋值
var b;
console.log(typeof a);->undefined
引用数据类型
Object
【对象】
类型检查[typeof]返回字符串
console.log(typeof b);
数据类型强制转换
->string
调用toString()方法
var a=123; a.toString(); console.log(typeof a); console.log(a); ->number ->123 //这个方法有返回值 var a=123; var b=a.toString(); console.log(typeof b); console.log(b); ->string ->123 a=a.toString();
boolean也可以用这个方法,但null,undefined不能
学到P68toString补
function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; } //创建一个person实例 ver person=new Person("vezzzing",2000,"m"); console.log(person); ->object Object var result=person.toString(); console.log(result); ->object Object
在页面打印对象时实际上是输出对象的toString()方法的返回值
function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; } //创建一个person实例 ver person=new Person("vezzzing",2000,"m"); console.log(person); ->object Object var result=person.toString(); console.log(result); ->object Object console.log(person.__proto__.__proto__.hasOwnProperty("toString") ->true
在这里
function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; } //创建一个person实例 ver person=new Person("vezzzing",2000,"m"); person.toString=function(){ return(this.name+this.age+this.gender) }; console.log(person); ->vezzzing2000m
修改toString方法
function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; } Person.prototype.toString=function(){ return(this.name+this.age+this.gender) }; //创建一个person实例 ver person=new Person("vezzzing",2000,"m"); console.log(person); ->vezzzing2000m
修改原型的toString方法
调用String()函数
var a=123; a=String(a);
->number
调用Number()函数
如果有非数值等无法转换
->NaN
空字符串,或全空格
->0
如果转换布尔值:T-1,F-0
null->0
undefined->NaN
parseInt()函数
专门针对字符串,提取有效数字
var a="123px" a=parseInt(a) ->123
parseFloat()函数
专门针对字符串,提取有效数字
->boolean
boolean()函数
数字除了0,NaN全为true
字符串除了空串全是true
null,undefined->false
对象转换为true
运算符
typeof运算符
算数运算符
利用这些特点做隐式类型转换
d=d-0;d=d/1;d=d*1
+-*/%(取余数)
非number的值运算会先转换为数字再运算
2*"8" 16
任何值与NaN运算生成NaN
全字符串自动拼接
任何值与字符串做加法先转换为字符串再拼接
1+2+“3”-33 “1”+2+3 -123
一元运算符
+-正负号
对于非number先转换为number再运算
a=true;a=-a->-1
可以对其他数据类型+转换为number
var result=1++"2"+3;->6
自增自减
var a=1; a++; console.log("a="+a); ->a=2 var a=1; ++a; console.log("a="+a); ->a=2
a++
++a
a--
--a
无论是哪种,都会立即使得原变量的值自增1,但是a++和++a的值不同
var a=1; console.log(a++); console.log("a="+a); ->1 a=2 var a=1; console.log(++a); console.log("a="+a); ->2 a=2
++a-新值
a++-旧值
逻辑运算符
!|| &&
为任意数值类型做两次非运算变布尔值
或短路
对于非布尔值进行与或运算
先转成布尔值再运算
然后返回原值
var result=1 && 2; ->2
赋值运算符
=,+=,-=,*=,/=,%=
关系运算符
><>=<=
相等运算符
==
条件运算符
(三元运算符)
条件表达式?语句1:语句2;
true?alert("语句1"):alert("语句2");
true->1,false->2
非布尔值转换成布尔值运算
应用
比较abc大小
var max=a>b?a:b; max=max>c?max:c;
var max=a>b?(a>c?a:c):(b>c?b:c);
utf编码输出
console.log("\u1C00")
\u+四位编码
这里用十六进制
网页输出
<h1>਼</h1>
这里用十进制
运算符优先级
跳过
我决定加括号
in运算符
检查对象里是否有某个属性
console.log("test2" in obj);
程序结构
代码块
用{}为语句statement分组,括起来以后要么都执行要么都不执行
PS:括起来叫做一组语句
代码块后面的}不用写;
JS中代码块只用来分组
代码块内部定义的变量外部也是可以调用的
流程控制
条件判断
if
if(条件表达式) 语句;
只能管理到其后一条语句
同Java
if分枝拦截
条件分枝
switch case
switch(条件表达式) case 表达式: 语句; break; case 表达式: 语句; break; default: 语句; break;
循环
<!DOCTYPE html> <html> <head> <title>JS质数判断</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="keywords" content="VEZZZING'S BILDINGS"> <meta name="description" content="StartAt2021.3.8"> <meta name="author" content="VEZZZING"> <script type="text/javascript" class="231"> var flag=true; for(var i=3;i<10000;i++){ flag=true; for(var num=2;num<i;num++){ if(i % num==0){ flag=false break; } } if(flag){ document.write(i+"<br>") } } </script> </head> <body> </body> </html>
while循环
while(条件表达式){ 语句; }
先判断再执行
do...while循环
do{ 语句; }while(条件表达式)
先执行再判断
for循环
for(初始化条件表达式,条件表达式,更新表达式){ 语句; }
初始化表达式→判断→执行语句→更新→判断
for循环略写
var i=0; for(;i<10;){ alert(i++); } >>>>>>>>>>>>>>>>>> for(;;){ //死循环 } >>>>>>>>>>>>>>>>>>
break
立即终止离他最近的循环语句
break在内层循环终止外层循环【指定特定循环】
outer: for(......){ for(......){ break outer; } }
continue
跳过当次循环
for(......){ if(i==2){ continue; } }
指定循环同break
对象
自定义对象
对象相关
object类型【复合数据类型】
对象分类
内建对象
Math String Number Function Object
ES标准中定义的对象,任何ES实现中都可以使用
宿主对象
由JS运行环境提供的对象【浏览器】
BOM DOM
console.log
自定义对象
创建对象
var obj=new Object();/*使用new关键字调用的函数叫做构造函数【constructor专门用来创建对象的函数】
使用typeof检查一个对象时返回object
使用console.log()输出object->Object{name="Vezzzing",gender="b",age="19"}
属性
向对象添加属性
对象.属性名=属性值;
obj.name="VEZZZING";
属性名
对象属性名命名不强制要求遵守标识符规范
特殊属性名的命名
对象["属性名"]=属性值
优点
[]中可以传递一个变量,变量是谁就读取哪个属性
ex:
obj["123"]=789; var n="123"; console.log(obj[n]);
读取也要这样
console.log(obj["123"])
属性值
可以是任意数据类型
var obj1=new Object(); var obj2=new Object(); obj1.name="233"; obj2.test=obj1; console.log(obj2.test.name); ->233
可以是对象
嵌套
in运算符
检查对象里是否有某个属性
console.log("test2" in obj);
读取对象属性
对象.属性名
console.log(obj.age);
找不到这个属性返回
修改对象属性
对象.属性名=新值
obj.name="Tom";
删除对象属性
delete 对象.属性名
枚举对象中的属性
ex:
取得document的属性
使用for..in语句
for(var 变量 in 对象){ }
for(var n in obj){ console.log(n);/*输出属性名*/ console.log(obj[n]);/*输出属性值,中括号用来传变量*/ }
方法【属性能传入任何对象,包括函数】
console.log();调用console的log方法
var obj=new Object(); obj.name="vezzzing" obj.age=2000 obj.sayName=function(){ console.log(obj.name); }; obj.sayName(); ->vezzzing
var obj2={ name:"vezzzing", age:18, sayName:function(){ console.log(obj2.name); } }; obj2.sayName();
基本数据类型和引用数据类型
内存结构
栈内存
基本数据类型存储在这里,独立储存
ex:
var a=123;
栈内存>变量名:a,变量值:123
结构
变量名
变量值
堆内存
ex:
var obj=new Object();
new表示在堆内存中开辟一块内存,以内存地址区分,假设这里分配内存地址为0x123
栈内存>变量名:obj,变量值:0x123
(变量值保存的是地址!!!!!!!)
堆内存>0x123内存空间
obj.name="vezzzing";
栈内存>变量名:obj,变量值:0x123
堆内存>0x123内存空间>name="vezzzing";
var obj2=obj
栈内存>变量名:obj,变量值:0x123
栈内存>变量名:obj2,变量值:0x123
栈内存>变量名:obj,变量值:0x123
obj2=null
栈内存>变量名:obj,变量值:null
栈内存>变量名:obj2,变量值:0x123
栈内存>变量名:obj,变量值:0x123
....所以
var a=123; var b=a; a++; console.log("a="+a); console.log("b="+b); ->a=124,b=123
var obj=new Object(); obj.name="vezzzing"; var obj2=obj; obj.name="meiiing"; console.log(obj.name); console.log(obj2.name); ->meiiing meiiing
var obj=new Object(); obj.name="vezzzing"; var obj2=obj; obj.name="meiiing"; obj2=null; console.log(obj); console.log(obj2); -> [object Object] null
var obj3=new Object(); var obj4=new Object(); obj3.name="vezzzing"; obj4.name="vezzzing"; colsole.log(obj3==obj4); ->false
(比较内存地址)
new时创建新的内存地址
总结
保存值,保存内存地址
对象字面量
创建对象的另一种方式
var obj={}; console.log(typrof obj); ->object
创建对象时直接指定属性
var obj={ name:"vezzzing", age="2000" };
var obj={name:"hik",pname:{name:"vezzzing"}}; console.log(obj.pname); ->vezzzing
用工厂方法创建对象
批量创建很多个相似的对象
var obj1={ name:"vezzzing", gender:"m", sayName:function(){ alert(this.name); } }; var ob2j={ name:"meiiing", gender:"f", sayName:function(){ alert(this.name); } };
function createPerson(name,gender){ //大批量创建对象 //创建一个新的对象 var obj=new Object(); obj.name=name; obj.gender=gender; obj.sayName=function(){ alert(this.name); }; return obj; } var obj1=createPerson("vezzzing","m"); var obj2=createPerson("meiiing","f");
使用工厂方法创建的对象,使用的构造函数都是Object
所以创建的对象都是object这个类型
导致无法区分不同类型的对象
->构造函数
构造函数
创建 方式根普通函数没有区别
不同的是构造函数首字母大写
function Person(){ //alert(this); this.name="vezzzing"; this.sayName=function(){ alert(this.name); }; } var per=new Person(); console.log(per.name) //这里this和per一样,this就是新建的对象 ->vezzzing
function Person(name){ //alert(this); this.name=name; this.sayName=function(){ alert(this.name); }; } function Dog(name){ //alert(this); this.name=name; this.sayName=function(){ alert(this.name); }; } var per=new Person("vezzzing"); var dog=new Dog("ww"); console.log(per.name); console.log(dog.name); //这里this和per一样,this就是新建的对象 ->vezzzing//这个是Person类的实例 ->ww//这个是是Dog类的实例
执行流程
1.new:立刻创建一个新的对象
2.将新建的对象设置为函数中的this
在构造函数中可以用this引用新建的对象
this.name="vezzzing";
3.执行函数中的代码
4.将创建的对象作为返回值返回
使用同一个构造函数创建的对象我们称为一类对象,也将一个构造函数称为一个类
通过构造函数创建的对象称为该类的实例
使用instanceof检查一个对象是否是一个类的实例
function Person(name){ //alert(this); this.name=name; this.sayName=function(){ alert(this.name); }; } function Dog(name){ //alert(this); this.name=name; this.sayName=function(){ alert(this.name); }; } var per=new Person("vezzzing"); var dog=new Dog("ww"); //这里this和per一样,this就是新建的对象 console.log(per instanceof Person); console.log(per instanceof Object); console.log(dog instanceof Person); ->true ->true ->false
function Person(name){ //alert(this); this.name=name; this.sayName=fun;//这样提升性能 } function Dog(name){ //alert(this); this.name=name; this.sayName=fun; } function fun(){ alert("this.name"); }; var per=new Person("vezzzing"); var dog=new Dog("ww"); console.log(per.name); console.log(dog.name); ->vezzzing//这个是Person类的实例 ->ww//这个是是Dog类的实例
但是尽量不要在全局作用域里面定义
可以这么做【写到原型对象里】
function Person(name){ //alert(this); this.name=name; } Person.prototype.sayName=function(){ alert(this.name); }; function Dog(name){ //alert(this); this.name=name; this.sayName=fun; } function fun(){ alert("this.name"); }; var per=new Person("vezzzing"); var dog=new Dog("ww"); console.log(per.name); console.log(dog.name); ->vezzzing//这个是Person类的实例 ->ww//这个是是Dog类的实例
创建构造函数时可以将这些对象共有的属性和方法添加到构造函数的原型对象中
这样不用分别为每一个对象添加,也不会影响到全局作用域
与普通函数的区别
调用方法
直接调用VSnew关键字调用
总结
this的三种情况
以函数的形式调用
this是window
以方法的形式调用
谁调用方法this就是谁
以构造函数的形式调用
this是新创建的那个对象
数组对象
数组也是一个对象
和普通对象相似,也是用来储存一些值的
但是普通对象使用字符串作为属性名,数组通过索引操作元素
数组创建
var arr=new Array();
使用字面量创建数组
可以在创建时就指定数组元素
var arr=[1,2,3,4,5,10;]
用构造函数也可以
var arr=new Array(10,20,30);
var arr=new Array(10);//创建长度为10的数组【用的不多】
元素可以放任何值
arr=["hello",1,true,null,undefiend];
也可以是对象
var obj={name:"vezzzing"}; arr[arr.length]=obj; console.log(arr[5].name); ->vezzzing
arr=[{name:"vezzzing",name:"meiiing"}];
也可以是函数
arr=[function(){alert(1)},function(){alert(2)}]; arr[0]();
也可以是数组
arr=[[1,2,3],[4,5,6]];
添加元素
arr[0]=10; arr[1]=33;
读取元素
console.log(arr[0]); ->10 console.log(arr[3]); ->undefined
获取数组长度
Array的length属性
console.log(arr.length);->2
只用于获取连续数组长度
对于非连续数组返回最大索引+1
不过尽量不要创建非连续数组
设置数组长度
修改length
arr.length=10;
修改的length多余原长度,多余的位置空出来
小于
最后的没有
向数组最后添加元素
arr[arr.length]=90;
数组的4个方法
push()
向数组末尾添加一个或多个元素,并返回数组新的长度
可以将要添加的元素作为方法的参数,这些元素会自动添加到数组末尾
arr.push("donggong");//添加 var result=arr.push("donggong"); console.log(result); ->5
pop()
删除并返回数组的最后一个元素
arr.pop(); result=arr.pop(); console.log(result); ->donggong
unshift()
向数组开头添加一个或多个元素,并返回新的长度
向前面插入元素后其他元素索引会依次调整
shift()
删除开头的第一个元素,并返回
数组遍历
for(var i=0;i<arr.length;i++){}
forEach方法
IE8以下不支持
arr.forEach()
需要一个函数作为参数
arr.forEach(function(){ console.log("vez"); }); -> vez vez vez
像这种由我们创建但不是由我们调用非函数成为回调函数
数组中有几个元素就执行几次
arr.forEach(function(a){ console.log(a); }); -> vezzzing meiiing donggong
浏览器将遍历到的元素以实参的形式传递进来,可以定义形参来读取这些内容
三位的参数含义(元素的值,元素的索引,就是正在遍历的数组对象)
slice和splice
slice方法
var arr=["vezzzing","meiiing","donggong","jianlong","laohu"]; var result=arr.slice(0,2); console.log(result); ->vezzzing,meiiing
在数组中提取指定的元素
arr.slice(start,end);
第二个参数省略不写截取从开始索引往后所有的值
索引可以传递一个负值(1,-1)倒数第一个
不会改变原数组而是将截取到的元素封装到一个新数组中返回
splice方法
删除元素并向数组添加新元素
var arr=["vezzzing","meiiing","donggong","jianlong","laohu"]; var result=arr.splice(0,2); console.log(result); ->vezzzing,meiiing console.log(arr); ->"donggong","jianlong","laohu"
第一位:起始位置,第二位,删除的数量,第三位,可以传递一些新的元素,这些元素会自动插入到开始位置索引前面
(1,0,“”,“”)添加元素
会对原数组产生影响
var result=arr.slice(0,1,"233","qwertyu");
数组其他方法
concat()
连接两个或多个数组,并将新的数组返回
var arrNew=arr.concat(arr2);//合并两个数组
var arrNew=arr.concat(arr2,arr3);//合并多个数组
var arrNew=arr.concat(arr2,arr3,"vezzzing");//元素也行
join()
将数组转换成字符串
result=arr.join(" ");//参数是连接符 ->vezzzing meiiing donggong
reverse()
颠倒数组顺序
arr.reverse();//直接修改原数组
sort()
对元素进行排序
arr=["a","c","b"]; arr.sort();//直接修改原数组 ->a,b,c
默认用的是Unicode编码,不能用来排数字
可以在sort()添加一个回调函数,来指定排序规则
回调函数需要定义两个形参
浏览器会分别以数组中的元素作为实参去调用回调函数
arr.sort(function(a,b){ });
a在数组中b前面
浏览器会根据返回值决定元素顺序:>0就交换位置,<=0不变
arr.sort(function(a,b){ if(a>b){ return 1; }else if(a<b){ return -1; }else{ return 0; });
return a-b;
内建对象
函数
函数也是一个对象
函数对象的创建
空白函数
var fun=new Function(); console.log(typeof fun); ->function
可以在构造函数里以字符串的形式传递JS代码【基本不用2333】
var fun=new Function( "console.log("love vezzzing,love meiiing" );
函数声明
function 函数名([形参1,形参2...形参N]){ 语句 }
function fun2(){ console.log("2333") }
function sum(a,b){ consoloe.log(a+b); }
浏览器不会检查实参类型,所以要进行类型检查
浏览器不会检查实参数量,多余实参不会参与赋值,如果实参数量的少于形参->undefined
使用函数表达式
var 函数名=function=function([形参1,形参2...形参N]){ 语句 };
实际上是以一个匿名函数赋值给变量
函数调用
fun(); ->love vezzzing,love meiiing
函数的返回值
function sum(a,b,c){ var d=a+b+c; return d; } var result=sum(1,2,3); console.log(result);
return后的语句不会执行
return不写值,或不写return->undefined
实参对象
var obj={ name:"vezzzing", age:"2000", gender:"B"} function printout(o){ console.log(o.name+o.age+o.gender); }
参数较多时可以考虑放入对象
实参为函数
可以匿名函数当实参
区分传函数本身还是返回值
函数返回值
返回值可以是对象
return {name="vezzzing"}
可以是函数
立即执行函数
匿名函数
(function(){ alert("这是匿名函数"); })();
();表示原地执行
(function(a,b){ console.log(a+b); })(123,456);
原型prototype
每创建一个函数【包括构造函数】解析器都会向函数中添加一个属性prototype
function Person(){} function MyClass(){} console.log(MyClass.prototype); console.log(MyClass.prototype==Person.prototype); ->object Object,false
这个属性对应着一个对象叫做原型对象
如果函数作为普通函数调用,这个prototype没有作用
作为构造函数调用 var mc=new MyClass();它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象
可以通过__proto__来访问
function MyClass(){} var mc=new MyClass(); var mc2=new MyClass(); console.log(mc2.__proto__=MyClass.prototype); consoel.log(mc.__proto__=MyClass.prototype); ->true ->true
原型对象相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象
可以将对象中公有的内容设置到原型对象中【静态方法,静态属性】
function MyClass(){} MyClass.prototype.a=123;//属性的添加 var mc=new MyClass(); var mc2=new MyClass(); console.log(mc2.__proto__=MyClass.prototype); consoel.log(mc.__proto__=MyClass.prototype); console.log(mc2.a); ->true ->true ->123
function MyClass(){} MyClass.prototype.a=123;//属性的添加 MyClass.prototype.sayHello=function(){ alert("hello"); };//方法的添加 var mc=new MyClass(); var mc2=new MyClass(); console.log(mc2.__proto__=MyClass.prototype); consoel.log(mc.__proto__=MyClass.prototype); mc.sayHello ->true ->true
原型对象
function MyClass(){} MyClass.prototype.name="name"; var mc=new MyClass(); mc.age=18; console.log(mc.name); ->name console.log("name" in mc); //用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也返回true ->true console.log(mc.hasOwnProperty("age")); //这个只有当对象自身含有某个属性时才返回true ->false console.log(mc.hasOwnProperty("hasOwnProperty")); ->false console.log(mc.__proto__.hasOwnProperty("hasOwnProperty")); ->false //说明这个hasOwnProperty方法也不在原型里
原型对象也是对象,所以它也有原型
当使用一个对象的属性或方法时,先在自身中找
如果没有
去原型对象中找
还是没有
去原型的原型中找
直到找到object对象的原型
还是没有
返回undefined
“原型链”
function MyClass(){} MyClass.prototype.name="name"; var mc=new MyClass(); mc.age=18; console.log(mc.name); ->name console.log("name" in mc); //用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也返回true ->true console.log(mc.hasOwnProperty("age")); //这个只有当对象自身含有某个属性时才返回true ->false console.log(mc.hasOwnProperty("hasOwnProperty")); ->false console.log(mc.__proto__.hasOwnProperty("hasOwnProperty")); ->false //说明这个hasOwnProperty方法也不在原型里 console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));
call&apply
函数对象的call方法
function fun(){ alert("v"); } fun.apply; fun.call; fun(); ->v ->v ->v function fun2(){ alert(this); } var obj=object fun2(); ->object Window fun2.call(obj); ->object object fin2.apply(obj); ->object object
改变this
call方法可以将实参在对象之后一次传递
fun.call(obj,2,3);
apply需要将实参封装到个数组中传递
fun.apply(obj,[2,3]);
总结
this
以函数形式调用
this永远是window
以方法形式调用
this是调用方法的对象
以构造函数的形式调用
this是新创建的对象
以call和apply调用
this是指定的那个对象
函数对象:fun,函数的返回值fun()
arguments
在调用函数时浏览器会传入两个隐含的参数
上下文对象this
封装实参的对象arguments
arguments是一个类数组对象【像数组,但不是数组】
也可以用索引获取数据
也可以获取长度
调用函数时,传递的实参都会在arguments中保存
function fun(){ console.log(arguments.length); console.log(arguments[0]; } fun("vezzzing","2"); ->2 ->vezzzing
与定不定义形参无关
arguments的callee属性对应一个函数对象,就是当前正在执行的函数对象
this详解
浏览器在调用函数时每次都会向函数内部传递一个隐含的参数
这个隐含的参数就是this
function fun(a,b){ console.log(this); } fun(123,456); ->object Window
this指向一个对象
根据函数调用方式不同this指向不同的对象
function fun(){ console.log(this); } fun(); var obj={ name:"vezzzing", sayName:fun }; console.log(obj.sayName==fun); obj.sayName(); -> object window object Object
以函数的形式调用时this永远是window
this.name
window的name全局变量的值[var name="name"]
以方法的形式调用时this就是调用方法的对象
this.name
obj.name
称为上下文对象
var name="全局" function fun(){ console.log(name); } var obj={ name:"vezzzing", sayName:fun } var obj1={ name:meiiing, sayName:fun } obj.sayName(); ->全局
var name="全局" function fun(){ console.log(this.name); } var obj={ name:"vezzzing", sayName:fun } var obj1={ name:meiiing, sayName:fun } obj.sayName(); ->vezzzing obj1.sayName(); ->meiiing
根据调用者的不同动态显示值
作用域
JS中一共有两种作用域
全局作用域
直接编写在script标签中的JS代码,都在全局作用域
在页面打开时创建,页面关闭时销毁
在全局作用域有一个全局对象window,可以直接使用
代表浏览器窗口,由浏览器创建
在全局作用域中创建的变量都会作为window的属性保存
var a=0; console.log(window.a);
在全局作用域中创建的函数都会作为window的方法保存
window.fun();
变量的声明提前
使用var关键字的变量会在所有代码执行之前声明
最早声明,执行到那一行时赋值
函数的声明提前
函数声明形式创建的(function函数(){})函数会在所有代码执行前就被创建
//函数声明,会被提前创建 function fun(){ console.log("fun"); } //函数表达式,不会被提前创建 var fun2=function(){ console.log("fun2"); };
可以在函数声明前调用,写在哪里都一样
全局作用域内的变量是全局变量,在程序内任意位置可访问
函数作用域
调用函数时创建,函数执行完毕后销毁
每调用一次产生一个独立的作用域
函数作用域内可以访问全局变量
var a=10; function fun(){ console.log("a="+a); } ->a=10
全局无法访问局部
在函数作用域操作一个变量时,它会先在自身作用域中寻找,若果有就直接使用,没有则向上一级作用域中寻找【重名时的情况】
ex
全局中,函数中都有a
函数嵌套中都有a
此时可以使用window对象
console.log("a="+window.a);
函数作用域也有声明提前,同上
函数中不使用var声明的变量都会变成全局变量
var c=33; function fun(){ c=10; d=100; } fun(); console.log(c) console.log(d) ->10 100
用来在函数里改变全局变量
定义形参相当于在函数中声明变量
Date构造函数对象
如果直接使用构造函数创建date对象,则会封装为当前代码执行的时间
var d=new Date();} console.log(d) ->....输出当下时间
创建指定的时间对象
需要传递字符串作为参数
var d2=new Date("12/03/2016 11:10:30");
一些方法
getDate();
获取当前对象中的时间是几号
var date=d2.getDate();
getDay();
返回一周中的某一天
0-6
getMonth();
11代表12月
getFullYear();
以四位数返回年份
getHours();
getMinutes();
getSeconds();
getMilliseconds();
getTime();
获取当前对象时间戳
从格林尼治时间1970.1.1.0.0.0到当前时间的毫秒数
计算机底层保存的都是时间戳
获取当前的时间戳
time=Date.now();
可以用来测试代码效率
Math工具类
不同于其他对象,它不是一个构造函数,属于一个工具类,不用创建对象
Math对象属性
E
e
LN2
ln2
LN10
ln10
LOG2E
log2e
LOG10E
PI
SORT1_2
1/sqr(2)
SORT2
sqr(2)
Math方法
abs(x)
用法Math.abs(1);
acos(x)
asin(x)
atan(x)
atan2(y,x)
返回从X轴到(x,y)的角度【-PI/2到PI/2弧度之间】
ceil(x)
上舍入
1.4->2
cos(x)
exp(x)
返回e的指数
floor(x)
log(x)
底数为e
max(x,y,z,...)
min(x,y,z,...)
pow(x,y)
x的y次幂
random()
0-1之间的随机数
round(x)
四舍五入为最接近的整数
sin(x)
sqrt(x)
平方根
tan(x)
toSource()
返回该对象的源代码
valueOf()
返回Math对象的原始值
包装类
JS中提供了三个包装类
通过这三个包装类可以将基本数据类型装换为对象
都是构造函数
String
字符串方法
在底层字符串以字符数组方式保存
str[5]
字符串方法
anchor() 创建 HTML 锚。
big() 用大号字体显示字符串。
blink() 显示闪动字符串。
bold() 使用粗体显示字符串。
charAt() 返回在指定位置的字符。
就是[]取字符
charCodeAt() 返回在指定的位置的字符的 Unicode 编码。
var result=str.charCodeAt(0);->72
concat() 连接字符串。
数组里面也有
对原字符串无影响
与+一样
fixed() 以打字机文本显示字符串。
fontcolor() 使用指定的颜色来显示字符串。
fontsize() 使用指定的尺寸来显示字符串。
fromCharCode() 从字符编码创建一个字符串。
写法特殊
result=String.fromCharCode(72);
result=String.fromCharCode(0x72);//转换为16进制【默认为16进制】
indexOf() 检索一个字符串中是否有指定字符。
str="hello"; result=str.indexOf("h"); ->0//第一次出现的位置 没有的话返回-1
第二个参数指定开始查找的位置
italics() 使用斜体显示字符串。
lastIndexOf() 从后向前搜索字符串。
用法同indexOf()
link() 将字符串显示为链接。
localeCompare() 用本地特定的顺序来比较两个字符串。
match() 找到一个或多个正则表达式的匹配。
replace() 替换与正则表达式匹配的子串。
search() 检索与正则表达式相匹配的值。
正则表达式
search()
可以搜索字符串中是否含有指定内容
var str="hello abc hello abc"; var result=str.search("abc"); con.... ->6 //没有的话返回-1
只会查找第一个,即使设置全局也内用
str.search(/a[bcd]f/);
match()
找到一个或多个正则表达式的匹配
var str="1a2b3c4d5e6f7"; var result=str.match(/[A-z]/); .. ->a
默认只会找到第一个符合条件的内容
可以设置为全局匹配来匹配所有内容
var str="1a2b3c4d5e6f7"; var result=str.match(/[A-z]/g); .. ->a,b,c,d,e,f
返回值是数组
可以为一个正则表达式设置多个匹配模式
str.match(/[a-z]/ig);
replace()
替换与正则表达式匹配的子串
result=str.replace("a","@");//用@替换a
默认只会替换第一个
这么匹配全部
resupstr.replace(/a/g,@);
slice() 提取字符串的片断,并在新的字符串中返回被提取的部分。
数组中也有
result=str.slice(0,2);
不该变原字符串
参数:开始位置(包括),结束位置(不包括)
只写第一个参数,截取到末尾
第二个参数负数表示倒数第几个
small() 使用小字号来显示字符串。
split() 把字符串分割为字符串数组。
有点像数组的join()
str="abc,bcd,efg,hij"; result=str.split(","); console..... ->"abc","bcd","efg","hij"
传入空串将每个字符拆分开
可以传入正则表达式拆分
var str="1a2b3c4d5e6f7" var result=str.split(/[A-z]/); ->1,2,3,4,5,6,7
strike() 使用删除线来显示字符串。
sub() 把字符串显示为下标。
substr() 从起始索引号提取字符串中指定数目的字符。
第二位是长度
substring() 提取字符串中两个指定的索引号之间的字符。
和slice基本一样
不同的是小何哥方法不能接收负值作为参数【负值自动使用0】
会自动调节参数位置
result=str.substring(1,0);//=str.slice(0,1);
sup() 把字符串显示为上标。
toLocaleLowerCase() 把字符串转换为小写。
toLocaleUpperCase() 把字符串转换为大写。
toLowerCase() 把字符串转换为小写。
toUpperCase() 把字符串转换为大写。
toSource() 代表对象的源代码。
toString() 返回字符串。
valueOf() 返回某个字符串对象的原始值。
Boolean
Number
var num=new Number(3); console.log(typeof num); ->object num.hello="abc"; console.log(num.hello); ->"abc" //基本数据类型不能添加属性
var num=new Number(3); var num2=new Number(3); console.log(typeof num); ->object num.hello="abc"; console.log(num.hello); ->"abc" //基本数据类型不能添加属性 console.log(num==num2); ->false
平时开发不用
浏览器自动包装和拆包临时创建对象【建后即销毁】来调用属性和方法
var s=123; s=s.toString(); console.log(s); console.log(typeof s); -> 123 string
基本数据类型没有属性和方法
正则表达式
用途
判断字符串是否符合格式
提取符合规则的字符串
创建
var 变量=new RegExp("正则表达式","匹配模式");
在构造函数中可以传递一个匹配模式
可以是
i
忽略大小写
var reg=new RegExp("a",i); var str="a"; console.log(reg.test("AbcAbc"); ->true//检查是否含有a
g
全局匹配模式
字面量创建
var 变量=/正则表达式/匹配模式
reg=/a/i
不灵活
上面那个可以传入变量
匹配模式
a或b
reg=/a|b/;
reg=/[ab]/;
检查是否有字母[-]
reg=/[a-z]/;
检查是否有数字
reg=/[0-9]/;
检查是否有abc/adc/aec
reg=/a[bde]c/;
^表示除了
reg=/[^ab]/; console.log(reg.test("abc"));->true
正则表达式方法
test()
检查字符串是否符合定义的规则
返回true/false
var reg=new RegExp("a"); var str="a"; console.log(reg.test("abcabc"); ->true//检查是否含有a
正则表达式语法
量词:指定一个内容出现的次数
/a{3}/
aaa
正好出现3次
/ab{3}/
abbb
/(ab){3}/
ababab
/ab{1,3}c/
abc
abbc
几到几次
abbbc
/ab{3,}c/
三次以上
n+ 匹配任何包含至少一个 n 的字符串
{1,}
n* 匹配任何包含零个或多个 n 的字符串
n? 匹配任何包含零个或一个 n 的字符串
检查字符串是否以a开头
/^a/
表示以a开头
abcabc
检查字符串是否以a结尾
/a$/
表示以a结尾
jhgjha
以a开头或以a结尾
/^a|a$/
元字符
转义字符表示原字符加上\
\\表示\
/\\/
字符串中还要转义
“\\\\"
元字符
. 查找单个字符,除了换行和行结束符。
\w 查找单词字符。
任意字母数字下划线
\W 查找非单词字符。
除了\w
\d 查找数字。
\D 查找非数字字符。
\s 查找空白字符。
去除两边的空格
str=str.replace(/^\s*|\s*$/g,"");
\S 查找非空白字符。
\b 匹配单词边界。
reg=/\bchild\b/; console.log(reg.test("hellochildren")); ->false
\B 匹配非单词边界。
\0 查找 NUL 字符。
\n 查找换行符。
\f 查找换页符。
\r 查找回车符。
\t 查找制表符。
\v 查找垂直制表符。
\xxx 查找以八进制数 xxx 规定的字符。
\xdd 查找以十六进制数 dd 规定的字符。
\uxxxx 查找以十六进制数 xxxx 规定的 Unicode 字符。
DOM
DocumentObjectModel文档对象模型
作用
通过JS操作HTML文档
文档
HTML文档
对象
网页中的每一个节点
模型
表示对象之间的关系
<html> <head> <title>网页标题</title> </head> <body> <a href="1.html">超链接</a> </body> </html>
模型结构
文档
html
head
title
文本节点
body
a
文本节点
节点的概念
网页最基本组成部分
网页中的每一个部分都是节点
类型也不一样
节点分类
文档节点
代表整个网页
元素节点
各种各样的标签
属性节点
id="pid"
文本节点
标签之间的文本
节点的属性
四种节点公有的属性
简单使用
浏览器已经为我们提供了文档节点,这个对象时window的属性
可以在页面中直接使用
文档代表整个网页
使用
<button id="btn">按钮</button> <script type="text/javascript"> var btn=document.getElementById("btn");//获取 //修改按钮的文字 btn.innerHTML="BUTTON"; </script>
事件
就是用户和浏览器之间的交互行为
点击按钮,鼠标移动,关闭窗口......
事件的处理
可以在事件对应的属性中设置一些JS代码
当这个事件被触发时,这些代码会执行
<button id="btn" ondbclick="alert('按钮被点击;')>按钮</button>
这种写法机构和行为耦合,不推荐使用
更好的写法
在script中为对象绑定响应函数
var btn=document.getElementById("btn"); btn.onclick=function(){ alert("按钮被点击"); };
文档的加载
浏览器加载页面的顺序
自上而下,读取到一行运行一行
将JS代码编写到页面最下面的原因
改变读取顺序
onload事件
会在整个页面加载完成之后触发
为window绑定onload事件
<head> <csript type="text/javascript"> winodw.onload=function(){ var btn=document.getElementById("btn"); btn.onclick=function(){} ...
确保所有对象已经加载完毕
DOM查询
获取元素节点
通过document对象获取
getElementById()
获取唯一元素
getElementsByTagName()
通过标签名获取一组元素节点对象
获取所有li节点
var list=document.getElementsByTagName("li");
返回一个类数组对象【即使查询到的元素只有一个】
getElementsByName()
通过name属性获取
< ... name="ged"....>
var list=documents.getElementsByName(); alert(list.length);
innerHTML
获取元素内部的HTML代码
<>内部HTML代码<>
修改内部HTML直接赋值
innerText
获取元素内部的文本内容
读取元素的属性值
元素.属性名
inputs[i].name
但是class属性不能这么读取
要这么写
元素.className
元素属性值的修改
元素.变量名=变量值
...innerHTML="2333"
获取元素节点的子节点
方法
getElementByTagName()
city.geyElementByTagName("li");
属性
childNodes
返回所有子节点
不仅仅只有元素ex:换行符
var cns=city.childNodes
children
获取当前元素的所有子元素
与childNodes区别
firstChild
也是子节点
lastChild
也是子节点
firstElementChild
第一个元素
获取父节点和兄弟节点
属性
parentNode
当前节点的父节点
previousSibling
前一个兄弟节点
previousElementSibling
前一个兄弟元素
nextSibling
获取body元素
var body=document.body;
获取html根标签
var html=document.documentElement;
获取页面中所有元素
var all=documrnt.all; for(...);//遍历
var all=document.getElementByTagName("*");
根据class查询
getElementByClassName();
根据CSS选择器查询
document.querySelector(".box1 div");
使用这个方法只返回唯一一个元素,如果满足条件的有多个也只返回第一个
document.querySelectorAll("....");
返回数组
即使只有一个符合条件也返回数组
DOM增删改
增
appendChild()
向一个父节点中添加子节点
父元素.appendChild(子节点);
createElement()
创建元素节点,需要一个标签名作为参数,根据标签名创建对象,并将创建好的对象作为返回值返回
createTextNode()
创建文本节点
var text=document.createTextNode("vezzzing");
insertBefore()
在指定的子节点前面插入新的子节点
父节点.insertBefore(newChild,resChild);
改
replaceChild()
替换子节点
父节点.replaceChild(new,old);
删
removeChild()
删除子节点
父节点.removeChild(子节点);
父元素未知的情况下删除元素
bj.parentNode.removeChild(bj);
用innerHTML实现增删改
var city=document.getElementById("city"); city.innerHTML+="<li>广州<li>";
DOM操作CSS
修改样式
元素.style.样式名=样式值
box.style.width="300px";
如果CSS样式名中含有-在JS中不合法,需要将这种样式名修改为驼峰命名法
backgroundColor
style中样式后加上!important就无法修改
只能设置内联样式
【stlye="..."】中的值
读取样式
元素.style.样式名
只能读取内联样式
元素.currentStyle.样式名
读取元素当前正在显示的样式【不是内联也不是外部】
只有IE支持
其他浏览器
getComputedStyle()方法,需要两个参数:要获取样式的元素,可以传递一个伪元素;一般传入null
返回一个对象,对象中封装了当前元素的样式:对象.样式名读取
alert(getComputedStyle(box1,null).width);
返回真实的样式值:ex:width->1500px;
兼容所有浏览器
function(obj,name){ if(window.getComputedStyle){//判断window有没有这个属性 return getComputedStyle(obj,null)[name]; }else{ return obj.currentStyle[name]; } }
总结
DOM方法
getElementById() 返回带有指定 ID 的元素。
getElementsByTagName() 返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。
getElementsByClassName() 返回包含带有指定类名的所有元素的节点列表。
appendChild() 把新的子节点添加到指定节点。
removeChild() 删除子节点。
replaceChild() 替换子节点。
insertBefore() 在指定的子节点前面插入新的子节点。
createAttribute() 创建属性节点。
createElement() 创建元素节点。
createTextNode() 创建文本节点。
getAttribute() 返回指定的属性值。
setAttribute() 把指定属性设置或修改为指定的值。
debug
chrome
F12
sources调试
垃圾回收GC
程序运行过程中会产生垃圾,这些垃圾积攒过多会导致运行速度过慢
什么是垃圾
var obj=new Object(); //这一步在栈内存的变量栏中添加一个名为obj的变量,值栏中添加一个指针,在堆内存中开辟一块储存区域 对对象进行各种操作 obj=null; //这一步断开指针连接但堆内存中内存还在 //这条语句提示浏览器对这个对象进行回收
tricks
document.write中换行
+"<br>
计时器
console.time("计时器名字");
console.timeEnd("计时器名字")
接收输入
var str=prompt("输入用户名:"); console.log(str);