JavaScript学习笔记
JS起源于1995年,用于处理网页中的前端验证。
前端验证:当网上冲浪越来越流行时,对于开发客户端脚本的需求也逐渐增大。此时,大部分因特网用户还仅仅通过 28.8 kbit/s(28kbit上传,28kbit下载) 的调制解调器连接到网络,即便这时网页已经不断地变得更大和更复杂。而更加加剧用户痛苦的是,仅仅为了简单的表单有效性验证,就要与服务器进行多次地往返交互。设想一下,用户填完一个表单,点击提交按钮,等待了 30 秒的处理后,看到的却是一条告诉你忘记填写一个必要的字段。这些类似的场景,在本地就可以很好的解决掉,而不需要服务器来处理,也就更进一步的促进了JS的发展和成熟。 JS与Javascript的区别:链接: link.
JavaScript引擎是执行JavaScript代码的程序或解释器。javaScript引擎可以实现为标准解释器或即时编译器,它以某种形式将JavaScript编译为字节码。
浏览器JS引擎实现方式开发公司FireFoxSpiderMonkey(蜘蛛猴)由Mozilla基金会与志愿者开发Chromev8(开源)由Google开发Internet ExplorerJScript/chakraMicrosoftv8会把js代码转换为高效的机器码,而不在是依赖于解释器去执行。 FireFox是Navigator浏览器(网景公司)前身。
–解释型语言(不用编译) –类似于C和Java的语法结构 –动态语言 –基于原型的面向对象
1.可以编写到标签的指定属性中
// 可以编写到标签的指定属性中 <button onclick="alert('hello');">按钮</button> <a href="javascript:alert('aa');">超链接</a>2.可以编写到script标签中
// 可以编写到script标签中中 <script type="text/javascript"></script>2.可以将代码编写到外部的js文件中,然后通过标签将其引入
// 可以编写到script标签中中 <script type="text/javascript" src="文件路径"></script>写在外部文件中,可以在不同的界面中同时引用,也可以利用到浏览器的缓存机制。 缓存机制:就是把一个已经请求过的web资源(如html页面,图片,JS,数据)拷贝一份放在浏览器中。缓存会根据进来的请求保存输入内容的副本。当下一个请求到来的时候,如果是相同的URL,浏览器会根据缓存机制决定是直接使用副本响应访问请求当(未超过缓存副本的有效期,304状态码)还是向源服务器再次发起请求(200)。
使用缓存机制原因 (1)减少网络带宽消耗 (2)降低服务器压力 (3)减少网络延迟 但缓存机制对开发者并不友好,因为当你更新页面后,但浏览器页面并未发生变化。 取消缓存机制:link.
1.弹出警示框
// 弹出警示框 alert("哥,你真帅");2.向控制台输出内容
//在页面中输出内容 console.log("哥,你真帅");3.在页面输出内容
//在页面中输出内容 document.write("哥,你真帅");字面量:不可改变的值 可直接使用,但一般不会直接使用。
// a 是变量,123是字面量 var a =123; // a是变量,“hello”是字面量 var a="hello";用以保存字面量。 声明变量 :使用关键字var 可通过变量对字面量进行描述。
在JS中可由自己命名的变量名、函数名、属性名。 JS底层保存标识符时实际采用Unicode编码。
规则:标识符中可以含字母、number、_、$。标识符不可以数字开头。不能为ES中的关键字或保留字采用驼峰命名法,首字母小写,每个单词的开头字母大写,其余字母小写。前五种为基本数据类型,Object为引用数据类型
所有的数值都是Number类型,包括整数和浮点数。 运算符:typeof 检查一个变量的类型 语法: typeof +变量
// 1.7976931348623157e+308 JS种表示数字的最大值 //5e-324 0以上的最小值 alert(Number.MAX_VALUE); alert(Number.MIN_VALUE);Infinity:正无穷。 用typeof 检查Infinity也会返回Number
NAN是一个特殊的数字,也会返回NumberNaN:Not a number 不是个数字 的 数字类型,一旦写程序出现NaN,那么肯定进行了非法的运算操作。 // NAN var a="abc"*"acd"; console.log(a); 使用JS进行浮点运算,就可能得到一个不精确的结果,不要用JS进行对精确度要求较高的运算。 // 0.30000000000000004 var c=0.1+0.2; console.log(c);使用typeof检查一个布尔值时,会返回"boolean"
Null类型值只有一个:null 用来表示一个空的对象
// 返回object var c=null console.log(typeof c);Undefined只有一个:undefined
// 返回undefined ,已声明,未赋值 var c; console.log(typeof c);Object 对象
调用被转换数据的toString()方法,不会改变原变量 只能将String、Number、Boolean类型转换为String
// string var a=123; var b=a.toString(); alert(typeof b);;调用String()函数,将被转换数据作为参数传给数据
// string var a=123; var b=String(a); alert(typeof b);;使用String()函数,对于Number和Boolean实际上就是调用toString()方法。对于null值,直接转换为字符串"null",对于undefined直接转换为字符串"undefined"
为任意的数据类型 +""
// string 123 var a=123; var b=a+""; alert(typeof b);;无toNumber()方法
1.字符串——>数字 如果为纯数字的字符串,直接转 如果存在非数字的字符串,转换为NAN 如果为空的字符串或全是空格,转换为0 2.布尔——>数字 true转为1,false转为0。 3.Null——>数字 输出0 4.Undefined——>数字 NaN
使用一元的+来进行隐式的类型转换
// number 123 var a="123"; a=+a; console.log(typeof a); console.log(a);为任意的类型做两次非运算,即可将其转为布尔值。
// boolean true var a=undefined; a=!!a; console.log(typeof a); console.log(a);获得一个值的类型,将该值类型以字符串形式返回.
// number var a=123; console.log(typeof a);(1)加法运算
//1 2 var result=true+false; console.log(result); var s=2+null; console.log(s);任何数与NaN做运算结果都是NaN.
//123456 string var result="123"+"456"; console.log(result); console.log( typeof result);任何值和字符串做加法运算都会先转成字符串,然后与字符串做拼串操作。可以利用该特点将任意类型转换为String,由浏览器自动完成,实际也是调用String()函数
//123hello string var result=123+"hello"; console.log(result); console.log( typeof result); //string var c=123; c=c+""; console.log(typeof c); //33 string 123 string var c=1+2+"3"; console.log( c); console.log(typeof c); c="1"+2+3; console.log( c); console.log(typeof c);(2)减法运算 除字符串加法,其余皆为转为Number计算
//c=99 var c=100-"1"; console.log( c);(3)乘法运算 Number类型值与undefined做乘法运算,结果为NaN.
//2NaN NaN var c=2*undefined; console.log( c); var b="2"*undefined; cosole.log(b);可以利用任何值在做减法、乘法、除法运算时会自动转为Number这一特点做隐式类型转换,原理与Number()函数一样。
//122 number var c="123"; c=c-1; console.log(c);(4)取模运算
–对于Number类型,不会对值产生任何影响
//123 var a=123; a=+a; console.log(a);–任意数据类型使用+号来将其转换为number,原理与Number()函数一样
//123 number var a="123"; a=+a; console.log(a); //6 var a==1++"2"+3; console.log(a);–符号取反
//-123 var a=123; a=-a; console.log(a);–对于非Number类型值,转为Number来进行运算
//-1 number var a=true; a=-a; console.log(a);a++与++a自增后,原变量的值会立即自增1.但a++与++a的值不同
a++ //2 1 var a=1; var b=a++; console.log(a); console.log(b); ++a //2 2 var a=1; var b=++a; console.log(a); console.log(b);a–与--a自减后,原变量的值会立即自增1.但a–与--a的值不同
a– //0 0 var a=1; var b=a--; console.log(a); console.log(b); –a //0 1 var a=1; var b=--a; console.log(a); console.log(b);–非布尔值的与运算: 第一个值为true,必然返回第二个值; 第一个值为false,必然返回第一个值;
(1)两者皆为true,返回后面的。
//2 var a=1&&2; console.log(a);(2)如果两个值中有false,则返回靠前的false.
//NaN var a=NaN&&0; console.log(a); 或||:JS中的或属于短路的或。 第一个值为true,必然返回第一个值; 第一个值为false,直接返回第二个值;= 、+=、-=、*=、/=、%=
条件表达式?语句1:语句2 如果条件表达式为非布尔值,先转为布尔值,再计算 javascript //语句1 "hello"?alert("语句1"):alert("语句2");
switch(条件表达式){ case表达式: 语句… break; . . . default: 语句… break; }
(2)0 1 2 3 4 5 6 7 8 9 javascript var i=0; for(;i<10;){ alert(i++); } 输入比较大小数值进行排序(正向、反向)。 使用方法:(1)冒泡排序法;(2)sort()方法以及reverse()方法。
代码链接: link.
break关键字可以退出switch或循环语句。不能在if中使用。 break只能终止与其最近的循环。 如果有两层循环,如果想终止外层循环,使用标记来标识。
// An highlighted block var foo = 'bar';<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript"> outer: for(var i=0;i<5;i++){ alert("外层循环"+i); for(var j=0;j<5;j++){ break outer; alert("内层循环"+j); } } </script> </head> <body> </body> </html>continue跳过当次循环
测试程序的性能 在程序执行前,开启计时器。console.time();用字符串作为参数 终止计时器console.timeEnd();
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> // 外层循环决定高度,内层循环决定宽度 console.time("time"); for(var i=1;i<=9;i++){ for(var j=1;j<=i;j++){ document.write("<span>"+i+"*"+j+"="+i*j+"</span>"); } document.write("<br/>"); } console.timeEnd("time"); </script> <style> span{ display: inline-block; width: 80px; } </style> </head> </html>基本数据类型都是单一的值,值与值之间没有任何的联系,对象子属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。
对象的分类: 1)内建对象。(在ES标准中定义的对象)在任何的ES的实现中都可以使用。eg. Math String Function 2)宿主对象。由JS的运行环境提供的对象,目前来讲主要是值由浏览器提供的对象。eg. BOM、DOM 3) 自建对象。
属性名:对象的属性名不强制要求遵守标识符的规范,但尽量按照标识符规范去做。 如果要使用特殊的属性名,不能使用.的发送来操作 语法: 对象[“属性名”]=属性值
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript"> var obj=new Object(); //obj.123=789;会报错 obj[123]=789; console.log(obj[123]); </script> </head> <body> </body> </html> 使用[]形式去操作属性,更加的灵活。 在[]中可以直接传递一个变量,这一变量值为多少就会读取那个属性。 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript"> var obj=new Object(); obj[123]=789; obj["你好"]="nihao"; var n=123; console.log(obj[n]); </script> </head> <body> </body> </html>属性值:JS对象的属性值,可以是任意的数据类型,甚至可以是一个对象
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript"> var obj=new Object(); obj.test=123; alert(obj.test);//123 var obj2=new Object(); obj2.name="猪八戒"; obj.test=obj2; alert(obj.test);//[object Object] alert(obj.test.name);//[猪八戒] </script> </head> <body> </body> </html>3.对象的属性值也可以是一个函数
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> var obj=new Object(); obj.name="孙悟空"; obj.sayName=function(){//匿名函数 alert(obj.name); }; obj.sayName(); </script> <body> </body> </html>函数成为一个对象的属性保存,则称函数为这个对象的方法。调用函数即为调用对象的方法。
语法:for(var 变量 in 对象){
}
// name age gender 孙悟空,18,男 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> var obj={ name:"孙悟空", age:18, gender:"男" } for(var n in obj){ console.log(n); alert(obj[n]); } </script> <body> </body> </html>1. 栈内存
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript"> var a=123; var b=a; a++; console.log("a="+a); console.log("b="+b); </script> </head> <body> </body> </html>基本数据类型的值都是直接在栈内存中存储,值与值之间独立存在,修改一个变量不会影响其他变量。 2. 堆内存 对象保存在堆内存中,每创建一个新的对象,就会在堆内中开辟一个新的空间。 变量保存的为对象的内存地址(对象的引用)。 如果两个变量保存的是同一个对象引用,一个变,另一个也随之改变。 当比较两个基本数据类型值时,就是比较值。 当比较两个引用数据类型值时,就是比较对象的内存地址。
var obj={};//等同于var obj=new Object(); console.log(typeof obj);//object 优点:使用对象字面量可以在创建对象时,直接指定对象的属性。 语法:{属性名:属性值,属性名,属性值…} var obj2={name:“猪八戒”}; 对象字面量的属性名可以加引号,也可以不加,建议不加,如果使用一些特殊的名字,则必须加引号。 属性名与属性值是一组一组的名值对结构。
函数也是一个对象,其中可以封装一些功能,在需要时执行。
方法一: (1)创建一个函数对象 var fun=new Function(); 使用typeof检查一个函数对象时,会返回function,可以将要封装的代码以字符串形式传递给构造函数。封装到函数中的代码不会立即执行,除非调用时。 eg. var fun=new Function(“console.log(‘hello’);”); (2)调用函数 函数对象() eg. fun();//此时代码会执行方法二: 使用函数声明来创建一个函数 语法:function 函数名([形参1,形参2,…形参n]){语句…}方法三: 使用函数表达式 赋值语句 var 函数名=function([形参1,形参2,…形参n]){语句…};在函数的()中指定一个或多个形参(形式参数),声明参数相当于在函数内部声明了相应的变量,未赋值。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function sum(a,b){ alert(a+b); } sum(1,2); </script> </head> <body> </body> </html>调用函数时解析器不会检查实参的类型,所以注意有可能会接收到非法的参数,如果有则需检查参数类型。 调用函数时解析器也不会检查非法的参数,,多余的不会被赋值。
使用return来设置函数返回值 语法:return 值; return;相当于return+undefined;不写return也相当于返回undefined。 1.练习一:
// 定义一个函数,判断一个数是否为偶数。 true,false <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function fun(num){ if(num%2==0){ alert("true"); } else{ alert("false"); } } var input=parseInt(prompt("请输入一个数:")); fun(input); </script> </head> <body> </body> </html>2.练习二: Number.isInteger()用来判断一个值是否为整数。但输入负数时 需要注意的是,在JavaScript内部,整数和浮点数是同样的储存方法,所以3和3.0被视为同一个值。
Number.isInteger(25) // true Number.isInteger(25.0) // true Number.isInteger(25.1) // false Number.isInteger("15") // false Number.isInteger(true) // false3.练习三:
// 定义一个函数,可以根据半径计算一个圆的面积并返回结果。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function fun(r){ //正整数 if(r%1==0){ return (Math.PI*r*r).toFixed(2);//结果保留两位小数 } //float else{ r=Math.floor(r*100)/100;//半径保留两位小数 return (Math.PI*r*r).toFixed(2); } } //求圆的面积,所以应为正数 var num=+(prompt("请输入一个正数:")); while(num<0||isNaN(num)==true){ num=+prompt("输入错误,请输入一个正数"); } var result=fun(num); alert("圆的面积为"+result); </script> </head> <body> </body> </html>4.练习四: 创建一个函数,在控制台输出个人信息。输出结果:我是孙悟空,我今年18岁了,我是男性,我住在花果山 (1)方法一:参数过多容易混乱
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function info(name ,age,gender,address){ console.log("我是"+name+",我今年"+age+"岁了,我是"+gender+"性,我住在"+address); } info("孙悟空",18,"男","花果山"); </script> </head> <body> </body> </html>实参可以是任意的数据类型,也可以是个对象。参数过多时,可以将其封装至对象中。 (2)方法二:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function info(obj1){ console.log("我是"+obj1.name+",我今年"+obj1.age+"岁了,我是"+obj1.gender+"性,我住在"+obj1.address); } var obj={ name:"孙悟空", age:18, gender:"男", address:"花果山" } info(obj); </script> </head> <body> </body> </html>此时哪怕对象中信息顺序变换(eg. name:"孙悟空"与age:18先后顺序变换),也不影响值的正确输出。 实参也可以是一个函数。 (1)调用函数对象
// a=function fun(r){ return Math.PI*r*r; } <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function fun(r){ return Math.PI*r*r; } function fun2(a){ console.log("a="+a); } fun2(fun); </script> </head> <body> </body> </html>(2)调用函数
// a=12.57 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function fun(r){ return Math.PI*r*r; } function fun2(a){ console.log("a="+a); } fun2(fun(2).toFixed(2)); </script> </head> <body> </body> </html>函数定义完立即被执行,只会执行一次。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> (function(){ alert("我是一个匿名函数~"); })();//如何不加会报错,调用函数(); </script> <body> </body> </html>作用域:变量的作用范围 在JS中有两种作用域:(1)全局作用域;(2)函数作用域
在页面打开时创建,页面关闭时销毁。在全局作用域中有一个全局对象(window),代表浏览器创建。 console.log(window);//[object window]
–在全局作用域中创建的变量都会作为window对象的属性保存。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> var a=10; console.log(window.a);//10 </script> <body> </body> </html>–在全局作用域中函数都会作为window对象的方法保存。
(1)使用var关键字声明的变量,会在所有代码执行之前被声明。不使用var关键字,则不会被声明提前。 (2)函数的声明提前:使用函数声明形式创建的function函数会在所有代码执行之前被创建。
// fun1 fun(); function fun(){ console.log("fun1"); }使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用。
// 报错,fun2()为方法,而fun2为变量 fun2(); var fun2=function(){ console.log("fun2"); }1.调用时创建函数作用域,函数执行完毕以后,销毁。每调用一次,便会创建一个新的函数作用域,他们之间相互独立。 2.在函数作用域中可以访问到全局作用域中的变量; 在全局作用域中不可以访问到函数作用域中的变量。 3. 当在函数作用域中操作一个变量时,它会在自身作用域中寻找,如果有就直接使用,如果没有就向上一级作用域中寻找。直到找到全局作用域,如果全局作用域中也没有,则会报错。
var a=10; function fun(){ var a="hello"; console.log("a="+a); } fun();//hello var a=10; function fun(){ var a="hello"; } fun(); console.log("a="+a);//10 在函数中访问全局变量a,使用window.a即可。在函数作用域中,也有声明提前的特性。函数声明也会在函数中所有代码执行之前执行。在函数中,不使用var声明的量都会变为全局变量。 var a=33; function fun(){ a=10; } fun(); console.log("a="+a);//108.定义形参相当于在函数作用域中声明了变量
var a=33; function fun(a){ alert(a); } fun();//undefined1.解析器在调用函数每次都会向函数内部传递一个隐含的参数,这个隐藏的参数就是this。this指向的是一个对象,称之为函数执行的上下文对象。 根据函数的调用方式不同,this会指向不同的对象。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function fun(){ console.log(this); } var obj={ name:"孙悟空", sayName:fun } obj.sayName(); fun(); //以上等同,不过前者为object object 后者为object window </script> <body> </body> </html>以函数的形式调用时,this永远就是window。 以方法的形式调用时,this就是调用方法的对象。 以构造函数形式调用时,this就是新创建的那个对象。 用call和apply调用时,this就是指定的那个对象。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function fun() { console.log(this.name);//调用哪个输出那个,更为方便 } var obj = { name: "孙悟空", age: 18, sayName: fun } var obj2 = { name: "猪八戒", age: 16, sayName: fun } obj.sayName(); obj2.sayName(); </script> <body> </body> </html>使用工厂方法创建对象,使用的构造函数都是Object.
//猪八戒 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function createPerson(name,age,gender){ var obj=new Object(); obj.name=name; obj.age=age; obj.gender=gender; obj.sayName=function(){ alert(this.name); }; return obj; } var obj2=createPerson("猪八戒",18,"男"); var obj3=createPerson("白骨精",18,"女"); obj2.sayName(); </script> <body> </body> </html>首字母大写,调用方式不同,构造函数需要new关键字来调用。 1.执行流程: (1)立即创建一个新的对象 (2)将新建对象设置为函数中this,在构造函数中可以使用this来引用新建的对象。 (3)执行函数中的代码 (4)将新建函数作为返回值返回。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; this.sayName=function(){ alert(this.name); }; } var per2=new Person("孙悟空",18,"男"); console.log(per2); </script> <body> </body> </html>2. 将通过一个构造函数创建的对象称之为该类的实例。 使用instanceof可以检查一个对象是否为一个类的实例 语法: 对象 instanceof 构造函数 eg. console.log(per2 instanceof Person);//true 所有的对象都是object的后代。任何对象和object做instanceof检查时都会返回true> 3.this的情况
调用方式this函数window方法谁调用this就是谁构造函数新创建的对象1.👍
// 大家好,我是孙悟空 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; this.sayName=function(){ alert("大家好,我是"+this.name); }; } var per2=new Person("孙悟空",18,"男"); per2.sayName(); </script> <body> </body> </html>在构造函数中,为每一个对象都添加了一个sayName 1中的方法是在构造函数内部创建的,也就是构造函数每执行一次就会创建一个新的sayName方法,这样导致如果该构造函数执行1000次,便会创建1000个一模一样的新的方法。 2.👍👍
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; this.sayName=fun; } function fun(){ alert("大家好,我是"+this.name); }; var per2=new Person("孙悟空",18,"男"); per2.sayName(); </script> <body> </body> </html>但将函数定义在全局作用域,污染了全局作用域的命名空间,也很不安全。
1.所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,即所谓的原型对象。 2.如何函数作为普通函数调用prototype时,没有任何作用。以构造函数形式调用时,它所创建的对象都会有一个隐含的属性,指向该构造函数的原型对象,通过_proto_访问该对象。 3. 原型对象就相当于一个公共的区域,所有的同一个类的实例都可以访问到这个原型对象。(可以将对象中共有的内容,统一设置到原型对象中)
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function MyClass(){ } var mc=new MyClass(); MyClass.prototype.sayHello=function(){ alert("hello"); } console.log(mc.__proto__); console.log(MyClass.prototype); </script> <body> </body> </html>mc._proto_与MyClass.prototype一样。 向MyClass的原型中添加属性a
MyClass.prototype.a=123; console.log(mc.a); mc.sayHello();123 hello 当访问对象的属性或方法时,其会在对象自身中寻找,有则使用,无去原型对象中寻找。 👍👍👍
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function Person(name ,age,gender){ this.name=name; this.age=age; this.gender=gender; } Person.prototype.sayName=function fun(){ alert("大家好,我是"+this.name); }; var ps=new Person("猪八戒",18,"男"); ps.sayName(); </script> <body> </body> </html>创建构造函数时,将这些对象共有的属性和方法统一添加到构造函数原型中。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> function MyClass(){ } MyClass.prototype.name="hello"; var mc=new MyClass(); console.log(mc.name);//hello console.log("name" in mc);//true console.log(mc.hasOwnProperty("name"));//flase </script> <body> </body> </html>in检查对象是否含有某个属性时,如果对象中没有,但原型中有,也会返回true。 使用hasOwnProperty()来检查自身中是否含有该属性。 原型对象也是对象,所有它也有原型。
在页面打印一个对象时,实际上输出的为对象的toString()方法的返回值。 当不希望在输出对象时输出[object Object],可以为对象添加一个toString()方法。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> function Person(name,age,gender){ this.name=name; this.age=age; this.gender=gender; } //创建一个per实例 var per=new Person("孙悟空",18,"男"); var per2=new Person("猪八戒",18,"男"); Person.prototype.toString=function(){ return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]"; } //只对per起作用,要想全部起作用,得对原型 // per.toString=function(){ // return "Psrson[name="+this.name+",age="+this.age+",gender="+this.gender+"]"; // } console.log(per);//object var result=per2.toString(); console.log(result);//string </object> </script> </head> </html>数组(Array):存储数据,普通对象使用字符串作为属性名,而数组使用数字作为索引操作元素。
创建数组对象。
var arr=new Array(); console.log(typeof arr);//object //也可以同时添加元素 var arr1=new Array(1,2,3); console.log(arr1);//Array(3) [ 1, 2, 3 ]向数组中添加元素 语法:数组[索引]=值
读取元素 语法: 数组[索引] 如果读取不存在的数组,不会报错,返回undefined
获取数组长度(元素的个数) 语法:数组.length (连续的数组)
var arr=[]; arr[0]=1; arr[1]=2; arr[2]=12; console.log(arr.length);//3对于非连续的数组,使用length会获取到数组的最大索引+1。
var arr=[]; arr[0]=1; arr[1]=2; arr[2]=12; arr[10]=13; console.log(arr.length);//11修改数组length。
向数组的最后一位添加元素。 数组[数组.length]=值
var arr=[]; arr[0]=1; arr[1]=2; arr[2]=12; arr[arr.length]=30; console.log(arr);//Array(4) [ 1, 2, 12, 30 ]push()方法:向数组末尾添加一个或多个元素,并返回数组新的长度。
var arr=["孙悟空","猪八戒","沙和尚"]; var s=arr.push("唐僧"); console.log(s); console.log(arr);pop()方法:删除数组的最后一个元素,并将被删除元素返回。
var arr=["孙悟空","猪八戒","沙和尚"]; var s=arr.push("唐僧"); console.log(arr); var t=arr.pop(); console.log(arr); console.log(t);unshift()方法:向数组开头添加一个或多个元素,并返回新的数组长度。
var arr=[1,2,3]; var s=arr.unshift(4,5,6); console.log(arr);//Array(6) [ 4, 5, 6, 1, 2, 3 ] console.log(s);//6shift()方法:删除并返回数组的第一个元素。
var arr=[1,2,3,4,5,6]; var result=arr.shift(); console.log(arr);//Array(5) [ 2, 3, 4, 5, 6 ] console.log(result);//1从数组中提取指定元素。 参数:截取开始的位置索引(包含开始索引);截取结束位置的索引(不包含结束索引),可省略不写。 该方法不会改变数组元素,而是将截取到的元素封装在一个新数组返回。
var arr=[1,2,3,4,5]; var result=arr.slice(0,3);// 1 2 3 console.log(result); var result1=arr.slice(2); console.log(result1);// 3 4 5splice()方法:删除数组的指定元素。会影响到原数组,并将删除的元素作为返回值返回。 参数:表示开始位置的索引;表示删除的数量;第三个及以后,可以传递新的元素,这些元素会自动插入到开始位置索引前边。
var arr=[1,2,3,4,5]; var s=arr.splice(1,3); console.log(arr);// Array [ 1, 5 ] console.log(s);//Array(3) [ 2, 3, 4 ] var arr=[1,2,3,4,5]; var result=arr.splice(0,1,6,7,8); console.log(arr);//Array(7) [ 6, 7, 8, 2, 3, 4, 5 ] console.log(result);//Array[1]conact()该方法不会对原数组产生影响。 可以连接两个或多个数组,并将新的数组返回,还可以传字符串。
var arr = [1, 2, 3]; var arr1 = [4, 5, 6]; var s = arr.concat(arr1); console.log(s);//Array(6) [ 1, 2, 3, 4, 5, 6 ]该方法可以将数组转为一个字符串。(不会对原数组产生影响,而是将转换后的字符串作为结果返回)
var arr=[1,2,4]; var s=arr.join(); console.log(typeof s);//string console.log(s);// 1 2 4在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符(默认为,)
var arr=["猪八戒","孙悟空","沙和尚"]; var result=arr.join("-"); console.log(result);//猪八戒-孙悟空-沙和尚反转数组该方法会直接修改原数组。
var arr=["猪八戒","孙悟空","沙和尚"]; arr.reverse(); console.log(arr);//Array(3) [ "沙和尚", "孙悟空", "猪八戒" ]对数组元素进行排序(会影响原数组,默认会按照Unicode编码进行排序)
var arr=["b","c","e","a","f"]; arr.sort(); console.log(arr);//Array(5) [ "a", "b", "c", "e", "f" ] var arr=[11,2,5,6,7,3]; arr.sort(); console.log(arr);//Array(6) [ 11, 2, 3, 5, 6, 7 ]即使对于传数字的数组,使用sort()排序时,也会按照Unicode编码来排序,所以对数组进行排序时,可能会得到错误的结果。 解决方案:自己指定排序的规则,在sort()添加一个回调函数来指定排序规则。 (1)回调函数中调用两个形参,浏览器会分别使用数组中的元素作为实参去调用回调函数。 (2)使用那个元素调用不确定,但肯定的时在数组中a一定在b前边。 (3)浏览器会根据回调函数的返回值来决定元素的顺序。
var arr=[11,2,5,6,7,3]; arr.sort(function(a,b){ return a-b; }); console.log(arr);//Array(6) [ 2, 3, 5, 6, 7, 11 ]在JS中提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象。 (1)String():将基本数据类型字符串转换为String对象。 (2)Number():将基本数据类型的数字转换为Number对象。 (3)Boolean():将基本数据类型的布尔值转换为Boolean对象。
实例
//地址不同,但Boolean可以 var num=new Number(3); console.log(typeof num);//object var num1=new Number(3); console.log(num==num1);//false在实际应用中基本不会使用基本数据类型的对象。因为如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果。
var bool=new Boolean(true); var bool2=true; console.log(bool==bool2);//true console.log(bool===bool2);//false ===恒等操作符(数值、地址相同)方法和属性只能添加给对象。不能添加给基本数据类型。
当我们去操作一个基本数据类型的属性和方法时, 解析器会临时将其转换为对应的包装类,然后再去操作属性和方法, 操作完成以后再将这个临时对象进行销毁。
Math:和其他的构造对象不同,他不是一个构造函数,它属于工具类,不用创建对象,其内封装了数学运算相关的属性和方法。
方法功能Math.ceil向上取整Math.floor向下取整Math.round四舍五入取整Math.random生成0-1之间的随机数Math.max获取多个数的最大值Math.pow(x,y)返回x的y次幂Math.sqrt()开方0-x的随机数 Math.round(Math.random()x) x-y的随机数 Math.round(Math.random()(y-x)+x)
定义一些字符串的规则。 计算机可以根据正则表达式来检查一个字符串是否符合规则或者将字符串中符合规则的内容提取出来。
创建正则表达式 var 变量=new RegExp(“正则表达式”,“匹配模式”); 正则表达式:object; 匹配模式:i:忽略大小写;g:全局匹配模式
正则表达式的方法。 test():检查一个字符串是否符合正则表达式规则。(true,false)
var reg=new RegExp("a"); var str="hello a"; var s=reg.test(str); console.log(s);//true使用字面量来创建正则表达式 语法: var 变量=/正则表达式/匹配模式 (1)检查一个字符串中是否含有a或b(忽略大小写)
var reg=/a|b/i; console.log(reg.test("a"));//true(2)创建一个正则表达式来检查一个字符串中是否含有字母。 [A-z]任意字母
var reg=/[a-z]/;//任意小写字母 console.log(reg.test("a"));//true(3) 检查一个字符串中是否含有abc或adc或aec
var reg=/a[bde]c/; console.log(reg.test("aec"));//true(4) 检查一个字符串中不含ab
var reg=/^[ab]/; console.log(reg.test("abcd"));//true量词:设置一个内容出现的次数。{n}正好出现n次
// a出现三次 var reg=/a{3}/; console.log(reg.test("aaabac"));//true //ab出现三次 var reg1=/(ab){3}/; console.log(reg1.test("abababac"));//true //b出现1-3次 var reg2=/b{1,3}/g; console.log(reg2.test("abbc"));//true var reg3=/ab+c/; console.log(reg3.test("abcs"));//true{m,n}出现n次; {m,}:m次以上; +:至少一次,相当于{1,}; *:0个或多个,相当于{0,}; ?:0个或1个,相当于{0,}; ^表示开头,$表示结尾。 检查一个字符串是否以a开头;是否是手机号;是否含有任意字符链接: link. \w:任意字母、数字、下划线; \W:除了字母、数字、下划线; \d:任意的数字; \D:除了数字; \s:空格; \b:单词边界;
DOM:文档对象模型。JS通过DOM对HTML文档进行操作。 (1)文档:表示整个的HTML网页文档。 (2)对象:表示将网页中的每一个部分都转换为一个对象。 (3)模型:表示对象之间的关系,方便获取对象。
节点(Node) (1)构成网页的最基本的组成部分,网页的每一个部分都可以称为是一个节点。
(2)节点的属性
节点nodeNamenodeTypenodeValue文档节点#document9null元素节点标签名1null属性节点属性名2属性值文本节点#text3文本内容浏览器已经提供了文档节点对象,这个对象是window属性,可以在页面中直接使用,文档节点代表的是整个网页。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript"> window.onload=function(){ var btn=document.getElementById("btn"); btn.innerHTML="I'm Button"; } </script> <body> <button type="button" id="btn">我是一个按钮</button> </body> </html> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> *{ padding: 0; margin: 0; } #left{ float: left; width: 25%; border: 1px solid black; margin: 10px 0px 0px 200px; padding: 10px; } #left ul{ display: inline-block; list-style: none; } li{ float: left; padding: 5px; background-color: #6495ED; margin: 5px; } #right{ float: left; width: 25%; margin: 10px; } .button{ width:300px; text-align: center; margin: 5px; } </style> <script type="text/javascript"> window.onload=function(){ // 创建一个“广州”节点,添加到#city下 myClick("btn01",function(){ //创建li元素节点 // 用于创建一个元素节点对象 // 它需要一个标签名作为参数,将会根据标签名创建元素节点对象 // 并将创建好的对象作为返回值返回 var li=document.createElement("li"); //创建li文本节点 // 用来创建文本节点对象 // 需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回 var gztext=document.createTextNode("广州"); //将gztext设置为li的子节点 // appendChild():向一个父节点中添加一个新的子节点 //语法: 父节点.appendChild(子节点) li.appendChild(gztext); //获取id为city的节点 var city=document.getElementById("city"); //广州添加到city中 city.appendChild(li); }); //将“广州”节点插入到#bj前面 myClick("btn02",function(){ //创建一个广州 var li=document.createElement("li"); var gztext=document.createTextNode("广州"); //将gztext设置为li的子节点 li.appendChild(gztext); //获取id为bj的节点 var bj=document.getElementById("bj"); //获取city var city=document.getElementById("city"); //insertBefore在指定的子节点前面放入新的节点,用父节点调用 //父节点.insertBefore(新节点,旧节点); city.insertBefore(li,bj); }); //使用“广州”节点替换#bj节点 myClick("btn03",function(){ //新建广州节点 <li>广州</li> var li=document.createElement("li"); var gz=document.createTextNode("广州"); li.appendChild(gz); //获取id为bj的节点 var bj=document.getElementById("bj"); //获取city,通过父节点进行替换 var city=document.getElementById("city"); //使用指定的子节点替换已有的子节点 city.replaceChild(li,bj); }); //删除北京节点 myClick("btn04",function(){ //获取id为bj节点 var bj=document.getElementById("bj"); //获取父节点city // var city=document.getElementById("city"); // //removeChild()删除一个子节点 // //父节点.removeChild(子节点); // city.removeChild(bj); //未知bj的父节点是谁 常用 //子节点.parentNode.removeChild(子节点); bj.parentNode.removeChild(bj); }); //读取#city内的HTML代码 myClick("btn05",function(){ //读取city var city=document.getElementById("city"); alert(city.innerHTML); }); //设置#bj内的HTML代码 myClick("btn06",function(){ //读取bj var bj=document.getElementById("bj"); bj.innerHTML="昌平"; }); //创建一个“广州”节点,添加到#city下 myClick("btn07",function(){ //相当于全删除重新添加的,如果那个列表里绑定了事件,则动作太大 //获取city var city=document.getElementById("city"); // city.innerHTML+="<li>广州</li>"; //结合使用 var li =document.createElement("li"); li.innerHTML="广州"; city.appendChild(li); }); } function myClick(idStr,fun){ var btn=document.getElementById(idStr); btn.onclick=fun; } </script> </head> <body> <div id="left"> <p>你喜欢哪个城市?</p> <ul id="city"> <li id="bj">北京</li> <li>上海</li> <li>东京</li> <li>首尔</li> </ul> </div> <div id="right"> <button class="button" id="btn01">创建一个“广州”节点,添加到#city下</button> <button class="button" id="btn02">将“广州”节点插入到#bj前面</button> <button class="button" id="btn03">使用“广州”节点替换#bj节点</button> <button class="button" id="btn04">删除#bj节点</button> <button class="button" id="btn05">读取#city内的HTML代码</button> <button class="button" id="btn06">设置#bj内的HTML代码</button> <button class="button" id="btn07">创建一个“广州”节点,添加到#city下</button> </div> </body> </html> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> #top { width:410px; margin: 50px auto; } table { border-collapse: collapse; } table,td,th { border: 1px solid black; padding: 0 17px; } #bottom { width: 410px; border: 1px solid black; margin: 50px auto; } .input{ width: 200px; padding: 5px; margin: 2px; } </style> <script type="text/javascript"> // 为Delete绑定单击响应函数 function delA() { //点击超链接后,删除超链接所在的哪一行 //响应函数里的this,绑定的谁就是谁 //获取当前tr var tr = this.parentNode.parentNode; //获取姓名 //var name=tr.firstChild;//此时需要tr 与td之间无空隙 var name = tr.getElementsByTagName("td")[0].innerHTML; //删除之前弹出提示框 // 用于弹出一个带有确认和取消按钮的提示框,需要一个字符串作为参数,该字符串将会作为提示符显示出来 //如果用户点击确认返回true,取消返回false var result = confirm("确认要删除" + name + "吗?"); if (true) { tr.parentNode.removeChild(tr); } //点击超链接后,超链接会跳转页面,这是超链接的默认行为 //取消该默认行为,通过在响应函数的最后return false来取消默认行为,或者在a中将href设为:javascript:; return false; } window.onload = function() { //点击超链接后,删除一个员工的信息 //获取所有超链接 var allA = document.getElementsByTagName("a"); //为每一个a绑定单击响应函数 //for循环会在页面加载完成后立即执行,而响应函数会在超链接被点击时才执行 //当响应函数执行时,for循环早已执行完毕 for (var i = 0; i < allA.length; i++) { //alert("for循环执行"+i+"次"); allA[i].onclick = delA; } //添加员工信息 //单击submit后响应事件 var btn = document.getElementById("btn"); btn.onclick = function() { //定义变量将用户输入的值保存 var name = document.getElementById("name").value; var email = document.getElementById("email").value; var salary = document.getElementById("salary").value; //新建tr var tr=document.createElement("tr"); //设置tr中的内容 tr.innerHTML="<td>"+name+"</td>"+ "<td>"+email+"</td>"+ "<td>"+salary+"</td>"+ "<td><a href='javascript:;'>Delete</a></td>"; //获取刚刚添加的a元素,并将其绑定单击响应函数 var a=tr.getElementsByTagName("a")[0]; a.onclick=delA; //获取table var table=document.getElementById("table"); //出现问题,新增的信息位于tbody的外面,新增的与原来的不是兄弟节点。 //获取table中的tbody var tbody=table.getElementsByTagName("tbody")[0]; tbody.appendChild(tr); }; } </script> </head> <body> <div id="top"> <table id="table"> <tr> <th>Name</th> <th>Email</th> <th>Salary</th> <th> </th> </tr> <tr> <td>Tom</td> <td>tom@tom.com</td> <td>5000</td> <td><a href="javascript:;">Delete</a></td> </tr> <tr> <td>Jerry</td> <td>jerry@sohu.com</td> <td>8000</td> <td><a href="deleteEmp?id=001">Delete</a></td> </tr> <tr> <td>Bob</td> <td>bob@tom.com</td> <td>10000</td> <td><a href="deleteEmp?id=001">Delete</a></td> </tr> </table> </div> <div id="bottom"> <div style="margin: 5px;text-align: center;" id="info"> <p style="text-align: left;font-size: 18px;font-weight: 500;">添加新员工</p> name: <input class="input" id="name" /></br> email: <input class="input" id="email" /></br> salary: <input class="input" id="salary" /></br> <button class="button" id="btn">Submit</button> </div> </div> </body> </html>获取父节点与兄弟节点(通过具体的节点调用) (1)parentNode:表示当前节点的父节点。 (2)previousSibling:表示当前节点的前一个兄弟节点。 (3)nextSibling:表示当前节点的后一个兄弟节点。
(1)获取body标签。
window.onload=function(){ var body=document.body; console.log(body); }(2)html根标签。 (3)页面中的所有元素
var all=document.all; for(var i=0;i<all.length;i++){ console.log(all[i]); }或者
var all=document.getElementsByTagName("*"); console.log(all.length);(4)根据元素的class属性值查询一组元素节点对象。
window.onload=function(){ var btn=document.getElementsByClassName("btn"); console.log(btn.length); }(5)document.querySelector() 包括(IE 8及以上) 需要用一个选择器的字符串作为参数,可以根据一个CSS选择器来查询一个节点对象。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript"> window.onload=function(){ var div=document.querySelector(".box1 div"); console.log(div.innerHTML);//hello } </script> </head> <body> <button type="button" class="btn">我是一个按钮</button> <div class="box1"> <div > hello </div> </div> </body> </html>使用该方法只会返回唯一的一个元素,如果满足条件的元素有多个,那么它只返回第一个。 (5) document.querySelectorAll():方法与4一样用法类似,不同的是它会将符合条件的元素封装到一个数组中返回。即使符合条件的元素只有一个,他也会返回数组。
创建li元素节点。 var li=document.createElement(“li”);
创建“广州”文本节点。 var gz=document.createTextNode(“广州”);
appendChild():向父节点中添加一个新的节点。 父节点.appendChild(新节点);
insertBefore():在指定的子节点前面放入新的节点,用父节点调用。 父节点.insertBefore(新节点,旧节点);
replaceChild():用指定的子节点替换已有的子节点。父节点.replaceChild(新节点,旧节点);
removeChild():删除一个子节点。 父节点.removeChild(子节点); 未知父节点:子节点.parentNode.removeChild(子节点);
获取节点的HTML代码:alert(节点.innerHTML);
设置节点的HTML代码:节点.innerHTML=“昌平”;
创建一个广州节点,添加至#city下。
具体代码 链接: link.
未加window之前,getComputedStyle为函数。如果未找到,全局找——>(没有)报错 加window,未找到返回undefined。
clientWidth 、clientHeight 这些属性都是不带px的,返回的都是一个数字,可以直接进行计算,会获取元素宽度和高度,包括内容区和内边距,这些属性都是只读不可修改 alert(box1.clientWidth);
offsetWidth offsetwidth 获取元素的整个宽度和高度,包括内容区、内边距和边框 alert(box1.offsetWidth);
offsetParent 获取当前元素的定位父元素 会获取到离当前元素最近的开启了定位的祖先元素(只要不是position 不是static就开启了定位)如果所有的祖先元素都没有开启定位,则返回body var op=box1.offsetParent; alert(op.id);
offsetLeft 当前元素相对于其定位元素的水平偏移量 offsetTop 当前元素相对于其定位元素的垂直偏移量 scrollHeight-scrollTop=clientHeight scrollWidth-scrollLeft=clientWidth
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <style type="text/css"> #box1{ width: 200px; height: 200px; background-color: beige; margin: 10px; overflow: auto; } #box2{ width: 400px; height: 300px; } </style> <script type="text/javascript"> window.onload=function(){ //获取box1 var box1=document.getElementById("box1"); var btn=document.getElementById("btn01"); btn.onclick=function(){ alert(box1.offsetLeft);//8 }; }; </script> </head> <body id="body"> <button id="btn01">点我一下</button> <!-- <div id="box2" style="position: relative;"> --> <div id="box1"> <div id="box2"> </div> </div> <!-- </div> --> </body> </html>1.事件的冒泡(Bubble):所谓的冒泡就是指事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发。 在开发中,大部分情况冒泡都是有用的,如果不希望发生冒泡事件,可以通过事件对象来取消冒泡 Event和window.event区别:link.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> #box1{ width: 200px; height: 200px; background-color: #FF7F50; } #s1{ background-color: antiquewhite; } </style> <script type="text/javascript"> window.onload=function(){ //获取s1,并为其绑定单击响应函数 var span=document.getElementById("s1"); span.onclick=function(event){ event=event||window.event; //取消冒泡 event.cancelBubble=true; alert("我是span的单击响应函数"); } //获取div,并为其绑定单击响应函数 var box1=document.getElementById("box1"); box1.onclick=function(event){ //兼容IE与其他浏览器 event=event||window.event; event.cancelBubble=true; alert("我是div的单击响应函数"); } //获取body,并为其绑定单击响应函数 document.body.onclick=function(){ alert("我是body的单击响应函数"); } } </script> </head> <body> <div id="box1">我是box1 <span id="s1">span</span> </div> </body> </html>事件的委派:指将事件同意绑定给元素的共同的祖先元素,这样当后代元素上的事件被触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。 事件委派其实利用了冒泡,通过委派可以减少事件绑定的此数,提高程序的性能。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> //为每一个超链接绑定单击响应函数 window.onload=function(){ //获取ul var ul=document.getElementById("ul"); //为每一个超链接都绑定了一个单机响应函数,操作麻烦,且该操作只能为已有的超链接设置事件 var aAll=document.getElementsByTagName("a"); // //遍历a // for(var i=0;i<aAll.length;i++){ // aAll[i].οnclick=function(){ // alert("我是a的单击响应函数"); // }; // } //希望绑定一次事件,即可应用到多个的元素上,即使元素是后添加的。 //尝试将其绑定给元素的共同的祖先元素 //事件的委派:指将事件同意绑定给元素的共同的祖先元素,这样当后代元素上的事件被触发时,会一直冒泡到祖先元素 //从而通过祖先元素的响应函数来处理事件 // -事件委派其实利用了冒泡,通过委派可以减少事件绑定的此数,提高程序的性能 ul.onclick=function(event){ //但是该区域点击都会响应函数,如果触发事件是期望的元素则执行 event=event||window.event; //target event中的target表示的是触发事件的对象 if(event.target.className="link"){ alert("我是ul的单击响应函数"); } }; //为button绑定单击响应函数 var btn=document.getElementById("btn01"); btn.onclick=function(){ var li=document.createElement("li"); li.innerHTML="<a href='javascript:;' class='link'>>新的超链接</a>"; ul.appendChild(li); }; }; </script> </head> <body> <button id="btn01">创建超链接</button> <ul id="ul"> <li><a href="javascript:;" class="link">超链接一</a></li> <li><a href="javascript:;" class="link">超链接二</a></li> <li><a href="javascript:;" class="link">超链接三</a></li> <li><a href="javascript:;" class="link">超链接四</a></li> </ul> </body> </html>综合:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> // 点击按钮后弹出一个内容 window.onload=function(){ var btn01=document.getElementById("btn01"); bind(btn01,"click",function(){ alert("1"); }); //定义一个函数,为指定元素绑定响应函数 //addEventListener()中的this.绑定的是事件的对象 //attachEvent()中的this.绑定的是window //统一两个方法this //参数: obj:要绑定事件的对象 eventStr 事件的字符串(不要on) callback 回调函数 function bind(obj,eventStr,callback){ if(obj.addEventListener){ //大部分浏览器兼容 //callback调用的是object HTMLButtonElement obj.addEventListener(eventStr,callback,false); }else{ //this是谁由调用方式决定 //IE及以下 obj.attachEvent("on"+eventStr,function(){ //本来是浏览器调用,现在变成自己调用 //callback调用本来是object window,自己调用 现在是object HTMLButtonElement callback.call(obj); }); } } }; </script> </head> <body> <button id="btn01">点我一下</button> </body> </html>事件的传播 -关于事件的传播网景公司和微软公司由不同的理解 -微软公司认为事件应该是由内向外传播,即当事件被触发时,应该先触发当前元素上的事件,然后再向上传播 即事件应该再冒泡阶段执行。 -网景公司认为事件应该是由外向内传播的,即当事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后再向内传递 w3c综合了两个公司的方案,将事件的传播分成了三个阶段。 1.捕获阶段:在该阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件 2.目标阶段:事件捕获到目标元素,捕获结束开始在目标元素上触发事件 3.冒泡阶段:事件从目标元素向它的祖先元素传递,依次触发祖先元素上的事件 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true,一般情况下不会希望在捕获阶段触发事件
1.onmousewheel鼠标滚轮滚动事件,会在滚轮滚动时触发,火狐不支持。 在火狐中使用DOMMouseScroll来绑定滚动事件 注意该事件需要通过addEventListener()函数来绑定。 2. 向上滚是正值,向下滚是负值 1)event.wheelDelta可以获取鼠标滚轮方向,不看大小,只看正负,火狐不支持。 2)event.detail适用于火狐。 3. 当滚轮滚动时,如果浏览器有滚动条,滚动条随之滚动 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为 4. 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false。 使用event来取消默认行为。 但是IE8不支持event.preventDefault(); event.preventDefault&&event.preventDefault();//实现兼容 完整代码
鼠标实现div拖拽
Navigator代表当前浏览器的信息,通过该对象可以识别不同的浏览器
由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了。因为在IE浏览器中很多地方需要兼容,所有很多网站选择在其他浏览器中最好的展现,在IE中功能完全即可,但用户体验不好就会认为是浏览器不好,在制作网页时,程序员会根据navigator.appName判断显示,结果为Navigator就最好展现, 显示Microsoft Internet Explorer就功能完全即可,所以IE为了挽回名声,在IE11浏览器里,如果使用navigator.appName会发现,显示Navigator,使得被同等对待,提升用户使用体验 一般只会使用userAgent来判断浏览器的信息。 userAgent是一个字符串,其包括有用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent。在IE11中已经将微软和IE相关的标识都已经去除了,所以基本不能通过UserAgent来识别一个浏览器是否是IE了。 判断浏览器信息History:对象可以用来操作浏览器向前或向后翻页.
length 属性,可以获取到当次访问的链接的数量 alert(history.length);back() 可以用来回退到上一个页面,作用与浏览器的后退一样。 eg. history.back();forward() 可以用来回退到上一个页面,作用与浏览器的前进一样。go()用来跳转到指定页面,需要一个整数作为页面 1表示向前跳转一个页面 -1表示向后跳转一个页面 2表示向前跳转两个页面Location 该对象中封装了浏览器的地址栏的信息。
如果直接打印Location,则可以获得到地址栏的信息(当前页面的完整路径)如果直接将location属性直接修改为一个完整的路径或相对路径,则页面会自动跳转页面,并会生成相应的历史记录。assign() 用来跳转至其他的页面,作用与直接修改location一样。reload() 重新加载当前页面,作用与刷新按钮一样。 如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面。replace() 使用一个新的页面替换当前页面,使用完毕也会跳转页面。不能使用回退按钮回退。 完整测试代码JS的程序的执行速度是非常高的,如果希望一段程序每间隔一段时间执行一次,使用定时器。 setInterval():定时调用,可以将一个参数,每隔一段时间执行一次。 参数: 1.回调函数,该函数每隔一段时间执行一次 2.每次调用间隔的时间,单位是毫秒1000毫秒即1秒 返回值:返回一个Number类型的数据,这个数字用来作为定时器的唯一标识
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <script type="text/javascript"> window.onload=function(){ var count=document.getElementById('count'); var num=1; var timer=setInterval(function(){ count.innerHTML=num++; if(num==11){ //关闭定时器 clearInterval(timer); } },500); }; </script> <body> <h1 id="count"></h1> </body> </html>键盘控制div移动 按钮控制div移动方向 图片切换
延时调用:延时一段时间不马上执行,而是隔一段时间后再执行,而且只会执行一次 浏览器打开后有一个大广告,用这个可以在15秒后关闭 延时调用和定时调用实际上是可以互相代替的。
var timer=setTimeout(function(){ alert(num); },1000); //关闭延时调用 //clearTimeout(timer);如果需要兼容IE7及以下的JSON操作,则可以通过引入一个外部的js文件来处理。
JSON:JS的对象只有JS自己认识,其他的语言都不认识 JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言识别 并且可以转换为任意语言中的对象,在开发中主要用来数据的交互。 JSON(JavaScript Object Notation JS)对象表示法 JSON格式与JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号,其他的与JS语法一致。 JS分类: 1.对象{} 2.数组[] JSON中允许的值:字符串 数值 布尔值 null 对象 数组
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <!-- 如果需要兼容IE7及以下的JSON操作,则可以通过引入一个外部的js文件来处理 --> <script type="text/javascript"> //创建一个对象,属性名加不加引号都可 var obj='{"name":"孙悟空","age":18,"gender":"男"}'; var arr='[1,2,3,"hello"]'; var obj2='{"arr":[1,2,3]}'; console.log(typeof obj);//string /** * JSON字符串转换为对象 * JS中,提供了一个工具类,就叫JSON * 这个对象可以帮我们将一个JSON转换为JS对象,也可以将一个JS对象转换为JSON * */ var json='{"name":"孙悟空","age":18,"gender":"男"}'; /** * JSON.parse() * 将JSON字符串转换为js对象 * 它需要一个JSON字符串作为对象,会将该字符串转换为JS对象并返回 */ var o=JSON.parse(json); console.log(o.name); var obj3={name:"孙悟空",age:18,gender:"男"}; /** * JS对象转JSON * 需要一个js对象作为参数,会返回一个JSON */ var str=JSON.stringify(obj3.name); console.log(str); /** * JSON对象在IE7及以下不支持 * */ </script>S </head> <body> </body> </html>只读的localStorage 属性允许你访问一个Document 源(origin)的对象 Storage;其存储的数据能在跨浏览器会话保留。localStorage 类似 sessionStorage,但其区别在于:存储在 localStorage 的数据可以长期保留;而当页面会话结束——也就是说,当页面被关闭时,存储在 sessionStorage 的数据会被清除 。
这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回 如果使用eval()执行的字符串中含有{},它会将{}当成是代码块 如果不希望将其当成代码块解析,则需要在字符串前后各加一个()
eval()这个函数的功能很强大,可以直接执行一个字符串中的js代码, 但是在开发中尽量不要使用,首先它的执行性能比较差,然后它还具有安全隐患
var str = '{"name":"孙悟空","age":18,"gender":"男"}'; var obj = eval("("+str+")");