最初是服务器端的语言,用来输入验证。
面向对象、解释型的程序设计语言。基于对象和事件驱动并具有相对安全性的客户端脚本语言。验证数据、加强用户体验。
松散型 变量不具有明显的类型
对象属性 javascript中的对象把属性名映射为任意的属性值
继承机制 继承机制是基于原型的
浏览器:
火狐 IE
谷歌 页面简洁 安卓系统的移动浏览器 (开放源代码)
苹果 safari 机器自带浏览器
opera 没有财力雄厚的大公司
完整的javaScript应该有 核心ECMAScript、文档对象DOM、浏览器核心对象BOM
ECMAScript(与web浏览器没有依赖关系 )
javascript基本语法、类型、语句、冠军案子、保留字、操作符、对象
我们常见的浏览器只是ECMAScript实现可能的宿主环境之一
DOM: html树 DOM把整个页面映射为一个多层节点结构
1、为什么要使用DOM
DHTML(Dynamic html)的出现使那个编写一个html页面就能够在任何浏览器运行的时代结束,但是如果继续保持web跨平台的天性w3C(word wide web万维网联盟)规划DOM
BOM:浏览器对象,它作为javaScript实现的一部分但是没有相关的标准,但是在h5中解决了
综上所述:javascript有三个不分组成:
1、ECMAScript提供核心语言功能
2、文档对象DOM:提供访问和操作网页的方法和接口
3、浏览器对象BOM:提供与浏览器交互的方法和接口
1、区分大小写
2、标识符组成 第一个字符必须是字母 下划线 美元符号
typeof 操作符+6大类型
1、Undefined 类型 typeof后返回的字符串是 undefined 没有定义的
2、Boolean 类型 typeof后返回的字符串是 boolean 布尔值
3、String 类型 typeof后返回的字符串是 string 字符串
4、Number 类型 typeof后返回的字符串是number 数值
5、Object 类型 typeof后返回的字符串是object 对象 null 空对象
6、function 类型 typeof后返回的字符串是function
申明了但是没有初始化的变量就是undefined。
没有申明直接使用的变量会出错
但是以上两种变量使用了 typeof 变量以后就会都成为undefined
表示空对象的引用 typeof null 返回object
null表示的没有创建对象的初始化
var box={} 此时的box为null 说明不是空对象,这个对象已经创建
var box=null 这个表示还没有创建对象,但先声明了对象引用而必须初始化的结果 后边使用的时候再初始化
alert(undefined==null) true
alert(undefined===null) false //数据类型必须相等
布尔类型
int 和float
int 二进制 八进制 十进制 十六进制
console.log(070); //56
console.log(0x70); //112
浮点类型
用e来表示过大或者过小的数值
不是数字类型 时为NaN 而且自己和自己也不相等
isNaN
console.log(isNaN(NaN)); //true
console.log(isNaN(true)); //false
console.log(Number(true)); //1
console.log(Number(25)); //25
console.log(Number(null)); //0
console.log(Number(undefined)); //NaN
var box={toString:function(){
return '123';
}}
console.log(Number(box)); //123
console.log(Number('wqwq12')); //NaN
console.log(parseInt(null)) //NaN
console.log(parseInt('1212wqwq12')) //1212
console.log(Number('1212wqwq12')) //NaN
console.log(Number(null)) //0
由0-16个字符来组成 单引号和双引号的意义是一致的
toString()方法
toString()方法可以将数值、布尔型转换成字符串
对象类型:一种引用类型将数据和功能结合在一起
创建对象:
1、 var box=new Object();
2、var box=Object();
3、var box={}; //字面量方式创建对象
4、box.name 或者box[‘name’]
给对象创建方法 box.run=function(){} //这个函数为匿名函数
对象包含哪些元素:1、属性2、方法 属性也可以带着单引号或者双引号
注意:函数的调用一定要有()
删除对象属性
delete 关键字
var box=new Object();
box.name='zhaowenjuan';
console.log(box.name); //zhaowenjuan
delete box.name;
console.log(box.name); //undefined
但是在实际的开发中比较受欢迎的是字面量的方法来定义对象
对象中 内置的方法
对象或者数组都有toLocalString、toString、valueOf
var box=['李彦辉',23,'sasa'];
console.log(box.toString()); //李彦辉,23,sasa
console.log(box.valueOf()); //["李彦辉", 23, "sasa"]
console.log(box.toLocaleString()); //李彦辉,23,sasa
但是这三个方式对日期对象是不一样的
var box=['李彦辉',23,'sasa',new Date()];
console.log(box.toString()); //李彦辉,23,sasa,Tue May 17 2016 16:06:47 GMT+0800 (中国标准时间)
console.log(box.valueOf()); //["李彦辉", 23, "sasa", Tue May 17 2016 16:06:47 GMT+0800 (中国标准时间)]
console.log(box.toLocaleString()); //李彦辉,23,sasa,2016/5/17 下午4:06:47
join()
这个方法调用的意思是将对象中的元素用 **连起来,返回的是一个字符串
var box=['李彦辉',23,'sasa',new Date()];
console.log(box.join('|')) ; //李彦辉|23|sasa|Tue May 17 2016 16:08:34 GMT+0800 (中国标准时间)
操作最后一个元素 push()和pop()
ESMAScript提供了一组让数组的行为类似于数据结构的方法
var box=['李彦辉',23,'sasa',new Date()];
console.log(box.push(45)); //将任意类型的数据添加到对象末尾,并返回添加后的长度
console.log(box.pop()); //移除对象的最后一个元素 返回的是被移除的元素
操作第一个元素 shift() 和unshift()
var box=['李彦辉',23,'sasa',new Date()];
console.log(box.shift()); // 移除对象的第一个元素 返回的是被移除的元素
console.log(box.unshift(45)); //将任意类型的数据添加到对象开头,并返回添加后的长度
注意:unshift这个由在IE浏览器有兼容性问题 返回的是undefined
排序 reverse() sort()
var box=[2121,23,'sasa','aa'];
console.log(box.reverse()); // ["aa", "sasa", 23, 2121]
console.log(typeof box.reverse()); // 返回的是排序后该对象
console.log(box.sort()); // [2121, 23, "aa", "sasa"]
sort详解
var box=[0,1,10,3,15,2];
function compare(v1,v2){
if(v1<v2){
return -1;
}
else if(v1>v2){
return 1;
}
else
return 0;
}
console.log(box.sort()); //[0, 1, 10, 15, 2, 3]
console.log(box.sort(compare)); //[0, 1, 2, 3, 10, 15]
第一句话 因为sort方法是吧数值当作字符了
slice ()和contact()
contact() 没有改变原的对象
var box=['sasa',121,'江苏'];
var box2=['sasa',121,'江苏'];
console.log(box.concat(box2)); //["sasa", 121, "江苏", "sasa", 121, "江苏"]
console.log(box); //["sasa", 121, "江苏"]
slice () 没有改变原的对象
var box=['sasa',121,'江苏'];
console.log(box.slice(1)); //[121, "江苏"]从2到末尾
console.log(box); //["sasa", 121, "江苏"]
splice()的三中功能
1、删除
var box=['sasa',121,'江苏','山西'];
console.log(box.splice(0,2)); //["sasa", 121]
console.log(box); //["江苏", "山西"]
2、插入
var box=['sasa',121,'江苏','山西'];
console.log(box.splice(1,0,'222')); //[] 因为没有删除 0表示不删除 当然也可以是非0 就成为了替换的功能
console.log(box); //["sasa", "222", 121, "江苏", "山西"]
3、替换
var box=['sasa',121,'江苏','山西'];
console.log(box.splice(1,1,'222')); //[121]
console.log(box); //["sasa", "222", "江苏", "山西"]
function类型实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针
函数的申明
1、function bb(){}
2、var bb=function(){} //使用变量初始化函数
3、var bb=new Function(){} //使用Function的构造函数
var bb=new Function('n1','n2','return n1+n2');
console.log(bb(1,2)); //3
console.log(typeof bb); //function
函数作为参数传递给其他函数
// 函数可以作为参数传递给其他函数
function bb(sum,num){
return sum(num)+num;
}
function sum(num){
return num+10;
}
console.log(bb(sum,10)); //sum是一个函数而不是返回值,当作参数传递给另一个函数 30
函数自身的属性
arguments和this
求阶乘
function sum(num){
if(num==1){
return 1
}
return num*sum(num-1);
}
console.log(sum(4));
arguments
利用函数自身的属性来求阶乘
function sum(num){
if(num==1){
return 1
}
return num*arguments.callee(num-1);
}
console.log(sum(4));
this
window是一个对象 js里边最大的对象,最外围的对象
console.log(typeof window); //object
console.log(this); //window 因为在window的范围下
console.log(typeof this); //object
var color='red'; //这里的color就是全局变量,这个变量有是window的属性 等价于window.color='red'
console.log(window.color); //red
console.log(this.color); //red
对象里边的color
var box={
color:'blue', //局部变量
sayColor:function(){
console.log(this.color); //this指的是box
}
}
box.sayColor(); //blue
length属性
有多少个参数
function aa(aa,bb){
return aa+bb;
}
console.log(aa.length); //2
prototype属性
对于prototype属性,保存所有实例方法的真正所在,也就是原型
有两个方法 apply() call() 每个函数都有这个方法
apply()方法 传递的必须是一个this 和一个数组
function aa(aa,bb){
return aa+bb;
}
function sum(num1,num2){
return aa.apply(this,[num1,num2]) //this表示window作用域,[]表示传递的参数
}
console.log(sum(10,10));
这样sum就冒充了aa的函数
function aa(aa,bb){
return aa+bb;
}
function sum(num1,num2){
return aa.apply(this,arguments) //this表示window作用域,[]表示传递的参数
}
console.log(sum(10,10));
这样也是正确的
call()方法 传递的必须是一个个的参数
function aa(aa,bb){
return aa+bb;
}
function sum(num1,num2){
return aa.call(this,num1,num2);
}
console.log(sum(10,10));
这两个都是用来改变作用域
var color='red';
var box={
color:'蓝色的'
}
function sayColr(){
console.log(this.color);
}
//用call来实现对象冒充 冒充box下,冒充window下
sayColr.call(window); //冒充window red
sayColr.call(this); //冒充window red
sayColr.call(box); //冒充box 蓝色的
变量类型:基本类型和引用类型
基本类型值:保存在栈内存的简单数据段,完全保存在内存中的一个位置
引用类型值:保存在堆内存中的指针 变量中指保存的是一个指针
基本类型:undefined null boolean number string 按照值来访问特别值得注意的是string是基本类型
引用类型:object 按照存储的地址来访问 也就是按引用来访问
动态属性:
var box=new Object();
box.name='lee'; //基本类型值 name就是一个动态属性
console.log(box.name);
复制变量
基本类型的复制了两个版本 完全独立的
引用类型的复制传递的是地址 只有一个具体的对象 指的是一个对象,改变会影响彼此
参数传递:
js中所有的参数都是按值来传递的,没有按引用传递的
function box(obj){
obj.name='lee';
var obj=new Object();
obj.name='kkk';
}
var obj=new Object();
box(obj);
console.log(obj.name); //lee js没有按引用传参的功能,
检测类型
检测一个变量的类型
使用typeOf 检测基本类型,但是对于引用类型typeof返回的都是object
使用instanceof 来检测引用类型
var box=[1,2,3];
console.log(typeof box); //object
console.log(box instanceof Array); //true
var ss='aa'; //这是一个字符串
var ss1=new String('aaa') //这是一个对象
作用域和内存
作用域链:当代码在一个环境中执行时,就会形成一种叫做作用域链的东西
基本包装类型:为了便于操作基本类型
ECMAScript提供了3种特殊的引用类型 Boolean Number String
1、基本包装类型的实例
是基本类型,但是是特殊的实例 可以调用系统内置的方法
var box='sasa2121'; //这是一个基本类型
console.log(typeof box);
console.log(box.substring(2)); //这明显是一个引用的方法的调用 只有对象才有方法
console.log('sasa212133'.substring(2)); //字符串本来就是基本包装类型
注意:基本类型是无法给自己添加属性和方法,但是可以使用系统自带的方法,不能添加自定义的方法
2、new运算符
这种使用new出来的对象自定义方法和属性都是有效的,内置的方法也是有效的
var box=new String('sasa2121'); //这是一个基本类型
box.name='lee'; //给对象加属性
box.age=function (){ //给对象加方法
return 100;
}
console.log(box.name); //lee
console.log(typeof box); //object
同样的原理类似于Boolean Number
属性
length:返回字符串的长度
constructor:返回创建string对象的函数
prototype:添加属性和方法来扩展字符串定义
var box='sasas';
console.log(box.length); //5
console.log(box.constructor); //String() { [native code] }
方法
字符
var box='sasas2122';
console.log(box.charAt(2)); //返回指定下标的值 s
console.log(box.charCodeAt(2)); //返回的是s的ascii码 115
操作
var box='sasas2122';
console.log(box.concat('is','sa')); //连接 sasas2122issa
console.log(box.slice(4,6)); //截取 s2
console.log(box.substring(4,6)); //截取 s2
console.log(box.substr(4,6)); //截取 s2122 从第4个开始选6个
//传递一个负数
console.log(box.slice(-3)); //9+(-3)=6从第6位开始 截取 122
console.log(box.substring(-3)); //负数返回全部 sasas2122
console.log(box.substr(-3)); //9+(-3)=6从第6位开始 截取 122
//传递两个数
console.log(box.slice(2,-1)); //9+(-1)=8 从第2位到第8位 截取 sas212
console.log(box.slice(-2,-1)); //从第7位到第8位 截取 2
位置处理
var box='sasas2122';
console.log(box.indexOf('s')); //0
console.log(box.indexOf('s',3)); //4 从前向后搜索
console.log(box.lastIndexOf('s')); //4 从后向前搜索
大小写转换
var box='sasa';
console.log(box.toLocaleLowerCase()); //sasa
console.log(box.toLocaleUpperCase()); //SASA
console.log(box.toLowerCase()); //sasa
console.log(box.toUpperCase()); //SASA
字符串匹配模式
var box='sasa';
console.log(box.match('s')); //["s", index: 0, input: "sasa"]
console.log(box.search('s')); //0
console.log(box.replace('s','q')); //qasa
console.log(box.split('s')); //["", "a", "a"] 按照s将字符串分割成数组
静态属性
Number的静态属性,直接通过类名来调用的属性
console.log(Number.MAX_VALUE); //静态属性
var box=100;
console.log(box.MAX_VALUE); //undefined 属性
内置方法
var box=10000;
console.log(box.toString()); //string 10000
console.log(box.toLocaleString()); //本地化数字转换为字符串 10,000
var bb=0.12122
console.log(bb.toFixed(2)); //0.12
global对象和math对象
内置对象:由ECMAScript实现提供的、不依赖宿主环境(浏览器)的对象。这些对象在ECMAScript程序执行之前就已经存在了。不需要程序员实例化。
全局对象,这个对象不存在。ECMA中不属于其他任何对象的属性和方法,都属于这个global的属性和方法
global对象的方法
1、URI编码 可以对链接中的非标准字符进行编码,以便发送给浏览器
console.log(encodeURI('//Lee里')); ////Lee%E9%87%8C 对/ ? #等特殊符号不编码
console.log(decodeURI(encodeURI('//Lee里'))); ////Lee里
console.log(encodeURIComponent('//Lee里')); //%2F%2FLee%E9%87%8C
console.log(decodeURIComponent(encodeURIComponent('//Lee里'))); //Lee里
//console.log(global); //会报错,证明根本没有这个对象
2、担当解析的作用
eval('console.log(111)'); //会在控制台输出111
但是这个函数比较危险,因为这个函数会直接执行。
global对象的属性
就是不属于任何对象的属性都属于global
ECMAScript保存数学公式
属性
e pi 等
方法
console.log(Math.min(1,4,6)); //1
console.log(Math.max(1,4,6)); //6
console.log(Math.ceil(25.1)); //26
console.log(Math.ceil(25.9)); //26
console.log(Math.floor(25.9)); //25
console.log(Math.round(25.1)); //25
console.log(Math.random()*10); //产生0-1的随机数,但是不包含0-1的随机数
当然也包含其他的平方根 绝对值 等的函数
ECMAScript有两种开发模式:1、过程 2、对象(类的概念)
通过类创建大量的对象的方式:
1、工厂模式:创建一个集中实例化的函数
function createObject(name,age){
var obj=new Object(); //创建对象
obj.name=name; //添加属性
obj.age=age; //添加方法
obj.run=function(){
return this.name+this.age+"运行中";
}
return obj; //返回对象引用
}
var cc=createObject('Lee',300);
var bb=createObject('Lee',100);
console.log(cc.run()); //Lee300运行中
console.log(bb.run()); //Lee100运行中
但是这种方式没有办法识别是那个对象的实例
2、构造函数创建
function createObject(name,age){
this.name=name; //添加属性
this.age=age; //添加方法
this.run=function(){
return this.name+this.age+"运行中";
}
}
var cc=new createObject('Lee',300);
var bb=new createObject('Lee',100);
console.log(cc.run()); //Lee300运行中
console.log(bb.run()); //Lee100运行中
工厂模式和构造函数的区别:
1、 构造函数没有new object 但是后台会自动的调用一个new object
2、构造函数中this就相当于obj
3、构造函数不需要返回对象的引用
4、使用构造函数生成对象的时候必须new 构造函数
5、构造函数也是函数
每一个函数都有prototype的属性,这个属性也是一个对象,用途是包含可以由特定类型的所有实例共享的属性和方法
实例方法和属性方法不同的实例化,他们的方法地址是不一样的,是唯一的。‘
原型方法,那么他们的地址是共享的,所有通过这个原型生成的对象的方法的引用都是一致的
//原型
function createObject(){}
createObject.prototype.name='Lee'; //原型属性
createObject.prototype.age=100;
createObject.prototype.run=function(){
return this.name+this.age+'运行中';
}
var bb=new createObject();
console.log(bb.run());
console.log(bb.prototype); //这个属性是一个对象,访问不到 undefined
console.log(bb.__proto__) //这个属性是一个指针,指向prototype原型对象
console.log(bb.constructor) //可以获取构造函数本身,
// 作用是被原型指针定位,得到构造函数本身,其实就是构造函数对应的原型对象
//判断一个对象实例(对象引用)是不是指向了原型对象,基本上只要实例化了自动指向他的原型对象
console.log(createObject.prototype.isPrototypeOf(bb)); //true
比较构造函数的生成对象的方式和原型生成的对象的方式
构造函数生成的两个对象在内存中的位置
原型生成的两个对象
是通过一个_proto的指针来指向的
实力的.constructor 可以获取构造函数本身
访问原型
function Box(){}
//使用字面量的方式创建原型对象,这里{}就是对象,是object,new Object就
var bb=new Box();
console.log(Box.prototype); //使用构造函数名(对象名)访问prototype
console.log(bb.prototype); //使用实例的prototype是访问不到的 undefined
console.log(bb.__proto__); //使用对象实例访问prototype的指针
原型的优点:实现属性和方法的共享
原型的缺点:某个实例修改后引用类型,保持了共享
function Box(){}
//使用字面量的方式创建原型对象,这里{}就是对象,是object,new Object就
Box.prototype={
constructor:Box,
name:'Lee',
age:100,
family:['哥哥','姐姐'],
run:function(){
return this.name+this.age+'运行中'
}
}
var bb=new Box();
console.log(bb.run()); //Lee100运行中
console.log(bb.family); //["哥哥", "姐姐"]
bb.family.push('妹妹');
console.log(bb.family); //["哥哥", "姐姐", "妹妹"]
var cc=new Box();
console.log(cc.family); //["哥哥", "姐姐", "妹妹"]
为了解决上述的问题,我们需要提出构造函数+原型模式来解决上述问题
function Box(name,age){
this.name=name;
this.age=age;
this.family=['哥哥','姐姐'];
}
Box.prototype={ //保持共享的原型
constructor:Box,
run:function(){
return this.name+this.age+'运行中';
}
}
这种混合模式很好的解决了传参和引用共享的难题,是创建对象比较好的方法
原型模式,不管你是否调用了原型中的方法,都会初始化原型中的方法,并且在申明一个对象时,构造函数+原型部分让人感觉很怪异,最好就是把构造函数和原型封装到一起,这种方式就是动态原型模式
1、将原型封装到构造函数里边,原型只要在第一次初始化就好了,没有必要每次实例化的时候都初始化
function Box(name,age){
this.name=name;
this.age=age;
this.family=['哥哥','姐姐'];
if(typeof this.run!='function'){
Box.prototype.run=function(){
return this.name+this.age+'运行中';
}
}
}
var bb=new Box('jushau',121); //jushau121运行中
console.log(bb.run());
以上就实现了原型第一次初始化就好了
function Box(){ //被继承的函数(父类或者基类)
this.name='Lee';
}
function Desk(){ //继承的类是(子类或者派生类)
this.age=100;
}
//通过原型链来继承
Desk.prototype=new Box(); //超类型实例化后的对象实例赋值给子类的原型属性
//new Box()会将Box构造里的信息和原型里的信息都交给Desk
var dd=new Desk();
console.log(dd.name); //Lee
console.log(dd.constructor);
/* Box(){ //被继承的函数(父类或者基类) this.name='Lee'; }*/
匿名函数:没有名字的函数,或者将自己的名字隐藏起来。
闭包:可访问一个函数作用域里变量的函数
注:单独的匿名函数是无法运行的。就算能运行也是无法调用的。
匿名函数的使用:
1、把匿名函数赋值给变量
var bb=function(){
return 'Lee';
}
2、通过表达式自我执行
(function(){ console.log('11'); })();
通过闭包访问局部变量
var bb=function(){
var age=100;
return function(){
return age;
}
}
console.log(bb()());
使用闭包有一个优点也是他的缺点,就是把局部变量驻留在内存中,可以避免使用全局变量。
//使用全局变量进行累加
var age=100;
function box(){
age++;
}
console.log(age)
box();
console.log(age);
//使用匿名函数实现驻留局部变量驻留内存中,从而进行不断地累加
function boxj(){
var age=100;
return function(){
age++;
return age;
}
}
var b=boxj();
console.log(b());
console.log(b());
console.log(b());
console.log(b());
由于闭包里作用域返回的局部变量资源不会被立刻回收,所以有可能会占用更多的内存,过多的使用闭包,会导致性能下降,建议在非常有必要的时候才使用闭包正确的是在使用完之后
b=null; 解除引用
闭包用于访问循环数组
//循环里的匿名函数的取值问题
function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=function(){ //
return i;
}
}
return arr;
}
// consoloe.log(box()); //返回的是一个函数数组
var b=box();
for(var i=0;i<5;i++){
console.log(b[i]()); //打印出来的都是5 是错误的
}
正确的 自我执行
//循环里的匿名函数的取值问题
function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=(function(){ //
return i;
})();
}
return arr;
}
// consoloe.log(box()); //返回的是一个函数数组
console.log(box());
利用闭包函数
function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=(function(num){
return function(){
return num;
}
})(i)
}
return arr;
}
var b=box();
for(var i=0;i<5;i++){
console.log(b[i]());
}
闭包中的window对象
在闭包中使用this对象会导致一些问题,this对象是在运行时基于函数的环境绑定的,如果this在全局范围内就是window,如果在对象内部就指向这个对象,而闭包却在运行时指向的是window的,因为闭包并不属于这个对象的属性和方法
var aa=function(){
return function(){
return this;
}
}
console.log(aa()()); //window
console.log(aa()); //会输出里边闭包的函数
一个实例来证明上述方法的正确性
var uu='huan';
var bb={
uu:'aa',
getuu:function(){
return function(){
return this.uu; //this指向了window
}
}
}
console.log(bb.getuu()()); //huan
想让闭包里边的this不指向window,
1、使用对象冒充成
var uu='huan';
var bb={
uu:'aa',
getuu:function(){
return function(){
return this.uu;
}
}
}
console.log(bb.getuu().call(bb)); //aa
2、把作用域变量存贮
var uu='huan';
var bb={
uu:'aa',
getuu:function(){
var that=this;
return function(){
return that.uu;
}
}
}
console.log(bb.getuu()()); //aa
由于IE的js对象和DOM对象使用不同的垃圾回收机制,因此闭包在IE中会导致一些问题。
内存泄漏:无法销毁驻留在内存中的元素。
解决的办法就是使用万多余的对象一定要将其置为null
私有化的好处:安全性、封装细节、程序可控性提高、数据保护
js中没有块级作用域: if for中的变量
//块级作用域(私有作用域)
function box(){
for(var i=0;i<5;i++){ //块级作用域(js没这个东西)
console.log(i);
}
console.log(i); //在这依然可以访问到i
}
var i; //就算重新声明但不初始化,也不会影响前面声明过的初始化的数据
box();
由以上的实例证明js中没有块级作用域
js模仿块级作用域
//块级作用域(私有作用域)
function box(){
(function(){ //包含自我执行的匿名函数就可以实现私有作用域
for(var i=0;i<5;i++){ //实现了块级作用域
console.log(i);
}
})()
var i;
console.log(i); //undefined
}
box();
使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁
使用全局变量以后也应该清空,但是这样会造成定义变量比较轻松。所以会使用自调用的方法俩实现私有变量的定义。
js没有私有属性,都是共有的。
function Box(){
this.age=100;
this.run=function(){
return this.age;
}
}
var bb=new Box();
console.log(bb.age); //100
js里边私有的属性+对外开放的接口
function Box(){
var age=100;
this.run=function(){
return age;
}
}
var bb=new Box();
console.log(bb.age); //undefined
console.log(bb.run()); //100
通过构造方法传递参数,但是这样传递的参数不会共享
function Box(age){
this.age=age;
this.run=function(){
return age;
}
}
var bb=new Box(10);
console.log(bb.age); //10
通过构造方法传递参数,实现属性共享 了uu
function Box(age){
var uu=age;
Box.prototype.getValue=function(){
return uu;
}
Box.prototype.setValue=function(age){
this.uu=age;
}
}
var bb=new Box('aa');
console.log(bb.getValue());
var vv=new Box('bb');
console.log(vv.getValue());
字面量方式私有化函数和方法
var box=function(){
var user='Lee'; //私有属性
var run=function(){ //私有方法
return '运行中';
}
return {
publicGo:function(){ //对外的公共接口
return user+run();
}
}
}();
console.log(box.publicGo()); //Lee运行中
js中浏览器对象模型:window对象 location对象 history对象
这个对象就是对浏览器进行操作的,但是这个对象缺少规范。
window对象
window对象下边有6个属性:这6大属性本身也是对象,
window对象旗下的document属性也是对象,
document旗下有5大属性也是对象
window对象里边的属性和方法 调用 window.属性 方法 或者 直接属性 方法
系统对话框 alert confirm prompt
confirm 有确定和取消
if(confirm('确定')){
console.log(1);
}
else{
console.log(2);
}
新建窗口
open('http://www.baidu.com')
1、第一个参数,是一个要将导航到的URL
2、窗口的名称或者窗口的目标
目标 :_blank新建一个窗口 _parent 在本窗口加载
3、宽度 高度 配置这个新的窗口 工具栏 地址栏
调用open()方法后返回的是window对象
var bb=open('http://www.baidu.com');
bb.alert('q111');
这时会在新的窗口弹出对话框
获取窗口的位置
alert(screenTop);
alert(screenLeft); //这两个属性有对IE浏览器的兼容性 是数字类型
兼容性:IE会left为0 top会算上菜单栏等
谷歌会正常显示 0 0
火狐根本就不认识这俩个属性 需要强制加window.screenTop undefined
火狐自己给自己提供了代替这两个属性的screenX screenY 谷歌也支持但是iE不支持
实现跨浏览器的方法
var leftX=(typeof window.screenLeft=='number')?screenLeft:screenX;
var leftY=(typeof window.screenTop=='number')?screenTop:screenY;
获取窗口的大小
innerHeight innerWidth
这两个属性在火狐窗口中是可视窗口的大小
IE浏览器不支持
window.outerWidth window.outerHeight
窗口的大小再加上窗口本身的边框
但是在谷歌浏览器中innerHeight=outerWidth 没有边框的问题
火狐浏览器会加一个边框
IE不支持 outerWidth
IE中想要或的可视窗口的大小 document.documentElement.clientWidth //谷歌和火狐也支持
获取可视窗口的大小的跨浏览器的方法
var width=window.innerWidth;
var height=window.innerHeight;
if(typeof width!='number'){
if(document.compatMode=='CSS1Compat'){ //用来判断是不是IE6
width=document.documentElement.clientWidth;
height=document.documentElement.clientHeight;
}
else{
width=document.body.clientWidth;
height=document.body.clientHeight;
}
}
移动窗口
moveTo(x,y) 移动到
moveBy(x,y) 在原来的基础上移动 谷歌不支持
调整窗口的大小
resizeTo(), resizeBy() 也有兼容性参数可以为负数
定时器
1、 setTimeout(函数,时间) 时间后执行这个函数 时间的单位是毫秒
会返回一个数值类型的ID
clearTimeou();
var bb=setTimeout(function(){
alert(1);
},2000);
clearTimeout(bb);
2、setInterval() 每隔一定的时间就会执行这个函数
var bb=setInterval(function(){
alert(1);
},2000);
clearInterval(bb);
定时器的实现
1、使用setInterval来实现定时器
var num=0;
var max=5;
var id=null;
function bb(){
num++;
document.getElementById('a').innerHTML+=num;
if(num==max){
clearInterval(id);
alert('时间到');
}
}
id=setInterval(bb,1000);
2、使用setTimeout实现
var num=0;
var max=5;
var id=null;
function bb(){
num++;
document.getElementById('a').innerHTML+=num;
if(num==max){
alert('时间到');
}
else{
setTimeout(this.callee(),1000);
}
}
setTimeout(bb,1000);
location对象既是window的对象,也是document的对象,其实就是URL
属性
location.search='?id=5'; //会实现让页面不停地跳
console.log(location.port); //会输出服务器的端口
得到页面传递的参数的实例
function getArgs(){
var search=location.search.length>0?location.search.substring(1):"";
var items;
var name=null,value=null,item=null;
var arr=[];
items=search.split('&');
for(var i=0;i<items.length;i++){
item=items[i].split('=');
name=item[0];
value=item[1];
arr[name]=value;
}
return arr;
}
var arr=getArgs();
注意:js中关系型数组,非数字索引数字的数组的长度为0
location对象的其他方法
1、跳转
location.assign(‘http://www.baidu.com‘);
location.reload(); //最有效的加载,有可能是从缓存中加载
location.reload(true); //强制加载,从服务器源头加载
location.replace(‘http://www.baidu.com‘) //替换当前页面,不会产生任何历史痕迹
location.href=’http://www.baidu.com’ //替换当前页面,会产生任何历史痕迹
属性:length 查看一共有多少条历史纪录
方法 :back() 向前 forward()向后
go()方法 里面可以传递参数 1为下一页 -1为上一页 -2为上两页 2为下两页
js识别浏览器,由于浏览器都有自己功能,在卡发阶段判断浏览器的类型是非常重要的
一、Navigator对象
1、浏览器以及版本号
alert(navigator.appName); //应该是得到浏览器的名称,但是这个方法不精确
alert(navigator.userAgent) //浏览器用户代理字符串
alert(navigator.platform) //浏览器所在的操作系统
2、浏览器嗅探器
浏览器嗅探器是一段程序,有了它,浏览器的检测就变得简单了。这里我们提供了一个browserdetect.js文件,来判断浏览器的名称,版本号,及操作系统
引入browserdetect.js文件在本地F盘js效果库
alert(BrowserDetect.browser); //浏览器的名称
alert(BrowserDetect.version); //浏览器的版本
alert(BrowserDetect.OS); //浏览器所在操作系统的名称
3、插件检测
是否支持播放音乐、视频、flash等插件
console.log(navigator.plugins.length);
for(var i=0;i<navigator.plugins.length;i++){
console.log('插件名'+navigator.plugins[i].name) //插件名字
console.log('文件名'+navigator.plugins[i].filename) //插件的磁盘文件名
console.log('描述信息'+navigator.plugins[i].description) //插件的描述信息
}
4、MIME类型
IE浏览器不识别
多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
alert(navigator.mimeTypes.length);
能力检测:浏览器是否具有某个功能
var width=window.innerWidth;
if(typeof width!='number'){
width=document.documentElement.clientWidth;
}
bug检测(检测缺陷)
var bb={
toString:function(){} //IE不识别toStirng()
}
for(var o in bb){
alert(o);
}
用户代理检测
浏览器引擎:用来排版网页和解释浏览器的引擎
IE Gecko(火狐的) Webkit(谷歌的) kHTML(Konquser) Opera(Opera浏览器)
D 文档 O对象 M模型
DOM的标准是由w3c来标准化的
节点分为3类:
1、元素节点:就是标签
2、文本节点:标签内的纯文本
3、属性节点:标签的属性
元素节点:构成了DOM的基础。文档结构中,是根元素,代表整个文档,其他的还有,,
,等等。元素节点之间可以相互包含(当然遵循一定的规则)
文本节点:包含在元素节点中。
属性节点:元素都可以包含一些属性,属性的作用是对元素做出更具体的描述,比如id,name之类的。
注意的是:DOM操作必须在文档加载完毕后,js代码才可以执行
1、将js代码放在正程序的最后边
2、使用window的onload()事件
window.onload=function(){
//存放当网页所有内容都加载完毕后,再执行的代码
}
1、document.getElementById(‘a’) a是一个id的名字IE5不兼容,但是几乎没有这种浏览器
1、tagName 获取元素节点的标签名 ()标签名大写
2、innerHTML :获取元素节点里面的内容 (单并非是w3c的标准) 可以解析html
var ss= document.getElementById('a') //但是IE不会支持
console.log(ss.tagName); //DIV
console.log(ss.innerHTML); //会把里面的ul 以及li都输出 是文本内容 但不是文本节点
元素节点的其他属性
var ss= document.getElementById('a') //但是IE不会支持
console.log(ss.tagName); //得到标签名字大写
console.log(ss.innerHTML); //会把里面的ul 以及li都输出
console.log(ss.title); //box
console.log(ss.style.color); //red style封装了的是一个对象
console.log(ss.class); //undefied
console.log(ss.className); //bb
html代码
<div id="a" title="box" class="bb" style="height: 100px;background:red;color:red" ><ul>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul></div>
元素的自定义属性
自定义属性 非IE不支持 尽量不去使用
2、document.getElementsByTagName()
window.onload=function(){
var li=document.getElementsByTagName('li'); //参数传递一个集合
console.log(li.length);
console.log(li.item(0)); //返回第一个li节点
console.log(li.item(0).tagName); //LI
}
注意:通过这个方法获取body节点的时候,一定要注意代码中只有一个body节点
document.getElementsByTagName(‘*’) 获取的是代码中所有的节点
3、document.getElementsByName()
4、getAttribute() //但是这种方法尽量避免使用
window.onload=function(){
var li=document.getElementById('a'); //
console.log(li.getAttribute('style')); //返回的是style里边的字符串,但是只能获取到的是行内的样式
}
console.log(li.getAttribute('class')); //bb 但是这个会有兼容性。IE获取不到
console.log(li.getAttribute('className')); //IE可以获取,非IE不可以获取
5、setAttribute()
window.onload=function(){
var li=document.getElementById('a'); //
li.setAttribute('title','表一'); //会为选择到的元素添加一个属性 title="表一"
li.setAttribute('align','center'); //元素会居中
}
6、removeAttribute()
window.onload=function(){
var li=document.getElementById('a'); //
li.removeAttribute('title'); //移除了属性 title
}
window.onload=function(){
var li=document.getElementById('a'); //
console.log(li.nodeType); //元素节点 这个值为1
console.log(li.nodeValue); //null
}
html代码
<div id="a" class="bb" style="background:red;color:green" >
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</div>
这些都是属性
childNodes
html代码
<div id="a" class="bb" style="background:red;color:green" >
测试<em>倾斜</em>结尾
</div>
js部分代码
window.onload=function(){
var li=document.getElementById('a'); //
console.log(li.childNodes); //nodelist 数组,返回当前元素节点的子节点的列表
console.log(li.childNodes.length); //3
//第一个子节点为测试 称作为文本节点
console.log(li.childNodes[0].nodeType); //3 表示的是文本节点 测试
console.log(li.childNodes[0].nodeValue); //获取文本节点的文本内容 测试
//第2个子节点为em 成为元素节点
console.log(li.childNodes[1].nodeType); //1 表示的是元素节点 em
//第三个子节点为结尾 称作为文本节点
console.log(li.childNodes[2].nodeType); //3 表示的是文本节点 结尾
}
innerHTML和nodeValue的区别
1、在得到了文本节点时候,是无法使用innerHTML这个属性输出文本内容的
2、innerHTML 的取值是可以包括html标签,并且解析html代码,但是nodeValue只是把html标签当作字符串来处理,并不会解析html代码
firstChild
等价于childNodes[0]
window.onload=function(){
var li=document.getElementById('a');
console.log(li.firstChild.nodeType); //3
console.log(li.firstChild.nodeValue); //测试
}
lastChild
window.onload=function(){
var li=document.getElementById('a');
console.log(li.lastChild.nodeType); //3
console.log(li.lastChild.nodeValue); //结尾
}
ownerDocumnet
window.onload=function(){
var li=document.getElementById('a');
console.log(li.ownerDocument); //HTMLDocument
console.log(document); //HTMLDocument 和上面是输出的是一样的
console.log(li.ownerDocument===document); //true
}
parentNode 、previousSibling、nextSibiling属性
parentNode 父节点
previousSibling 同级节点的上一个节点
nextSibiling 同级节点的下一个节点
window.onload=function(){
var li=document.getElementById('a');
console.log(li.parentNode.nodeName); //BODY
console.log(li.firstChild.nextSibling); //<em>倾斜</em>
console.log(li.lastChild.previousSibling.nodeName); //EM
}
html代码
<div id="a" class="bb" style="background:red;color:green" >
测试<em>倾斜</em>结尾
</div>
js代码
window.onload=function(){
var li=document.getElementById('a');
console.log(li.attributes); //NameNodeMap 集合数组,保存着这个元素节点的属性列表
console.log(li.attributes.length); //3
console.log(li.attributes[0]); //id="a"
console.log(li.attributes[0].nodeType); //2 属性节点的类型值是2
console.log(li.attributes[0].nodeValue); //a
console.log(li.attributes[0].nodeName); //id
}
空白文本节点的处理
问题的出现
html代码
<div id="a" class="bb" style="background:red;color:green" >
<p>sajisa</p>
<p>sajisa</p>
<p>sajisa</p>
</div>
js代码
window.onload=function(){
var li=document.getElementById('a');
console.log(li.childNodes.length); //7 理应输出3但不是
}
解决方案 1、忽略空白字符 2、移除空白字符
1、忽略
function filterWhiteNode(node){
var ret=[];
for(var i=0;i<node.length;i++){
if(node[i].nodeType===3&&/^\s+$/.test(node[i].nodeValue)){
continue;
}
else{
ret.push(node[i]);
}
}
return ret;
}
window.onload=function(){
var li=document.getElementById('a');
console.log(filterWhiteNode(li.childNodes).length); //3
}
2、移除
//这个函数为要去除空空白文本节点的一个集合
function filterWhiteNode(node){
for(var i=0;i<node.length;i++){
if(node[i].nodeType===3&&/^\s+$/.test(node[i].nodeValue)){
node[i].parentNode.removeChild(node[i]);
}
}
return node;
}
window.onload=function(){
var li=document.getElementById('a');
console.log(filterWhiteNode(li.childNodes).length); //3
}
可以动态的创建、复制、删除节点
添加节点
1、创建节点 2、插入节点 createElement appendChild
window.onload=function(){
var li=document.getElementById('a');
var bb=document.createElement('p');
var tt=document.createTextNode('测试文档4'); //创建文本节点
bb.appendChild(tt);
li.appendChild(bb)
}
2、insertBefore使用这个方法的前提是必须先跳到父节点
window.onload=function(){
var li=document.getElementById('a');
var bb=document.createElement('p');
var tt=document.createTextNode('测试文档4'); //创建文本节点
bb.appendChild(tt);
li.parentNode.insertBefore(bb,li); //这样就会在li的前边插入一个P
}
模拟向某个元素的后边插入一个元素
html代码
<span>开始</span>
<div id="a" class="bb" style="background:red;color:green" >
<p>sajisa</p>
<p>sajisa</p>
<p>sajisa</p>
</div>
</body>
<span>结束</span>
js代码
window.onload=function(){
var li=document.getElementById('a');
var bb=document.createElement('p');
bb.setAttribute('tt','aa'); //给插入的节点添加了一个属性
insertAfter(bb,li); //这样就会在li的后边插入一个p节点
}
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;
if(parent.lastChild==targetElement){
parent.appendChild(newElement,targetElement)
}
else{
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
上述执行后的结果就是在id为a的div后插入一个p节点
3、克隆方法 clone
window.onload=function(){
var li=document.getElementById('a');
filterWhiteNode(li.childNodes);
var cc=li.firstChild.cloneNode(true);
li.appendChild(cc);
}
//这个函数为要去除空空白文本节点的一个集合
function filterWhiteNode(node){
for(var i=0;i<node.length;i++){
if(node[i].nodeType===3&&/^\s+$/.test(node[i].nodeValue)){
node[i].parentNode.removeChild(node[i]);
}
}
return node;
}
li.firstChild.cloneNode(true);
参数为true时,就是把标签内的文本也克隆,
参数为false时,只克隆标签,不克隆里边的内容
4、删除子节点 removeChild()
1、node类型
2、Document类型 文档或者文档的根节点
获取body节点的方法
var dd=document.getElementsByTagName('body')[0];
var ss=document.body;
window.onload=function(){
var dd=document.getElementsByTagName('body')[0];
var ss=document.body;
console.log(document.title); //Document
console.log(document.URL); //http://localhost:63342/baidu%20kaifangyun/Person/test.html
console.log(document.domain); //localhost
console.log(document.referrer); //获取上一个访问过的url
console.log(document.forms); //获取文档中的<form>集合
console.log(document.images); //获取文档中的<image>集合
console.log(document.links); //获取文档中的有href的a集合
document.title='sahsua';
}
3、Element类型
元素节点的类型
4、Text类型
文本不包含HTML,NodeType为3
在创建同一节点的文本节点的时候,会产生分离的两个节点
html代码
<div id="a" class="bb" style="background:red;color:green" >MYSha</div>
js代码
window.onload=function(){
var bb=document.getElementById('a');
var cc=document.createTextNode('Mu');
bb.appendChild(cc);
console.log(bb.childNodes.length); //2
bb.normalize(); //合并同一级别的两个文本节点
console.log(bb.childNodes.length); //1
console.log(bb.childNodes[0].nodeValue) //MYShaMu
bb.firstChild.splitText(4);
console.log(bb.childNodes[0].nodeValue) //MYSh
bb.normalize(); //合并同一级别的两个文本节点
bb.childNodes[0].deleteData(0,3);
console.log(bb.childNodes[0].nodeValue) //haMu
bb.childNodes[0].insertData(0,'hsaush');
console.log(bb.childNodes[0].nodeValue) //hsaushhaMu
bb.childNodes[0].replaceData(0,2,'mess');
console.log(bb.childNodes[0].nodeValue) //messaushhaMu
}
5、注释类型
6、属性节点类型
1、在IE中没有文档申明的时候就会出现怪异模式
节点的属性:
window.onload=function(){
var bb=document.getElementById('a');
alert(bb.innerText); //获取div里边的文本内容,并且过滤掉HTML。
bb.innerText='<strong>sasa</strong>' //直接设置,不会解析他当中的html代码
}
表格:
window.onload=function(){
//使用DOM来创建一个表格
var table=document.createElement('table');
var caption=document.createElement('caption');
caption.innerHTML='人员表'; //或者是创建文本节点并将其插入
var thead=document.createElement('thead');
var tr=document.createElement('tr');
var td1=document.createElement('td');
var td2=document.createElement('td');
td1.innerHTML='数据2';
td2.innerHTML='数据2';
tr.appendChild(td1);
tr.appendChild(td2);
thead.appendChild(tr);
table.border=1;
table.setAttribute('width',300);
table.appendChild(caption);
table.appendChild(thead);
document.body.appendChild(table);
}
使用DOM来获取table中的数据
window.onload=function(){
//使用DOM来获取表格里边的数据
var table=document.getElementsByTagName('table')[0];
console.log(table.children[2].children[2].children[2].innerHTML);
}
这种方法他复杂,而且没有用到table的有利的地方
html代码
<table border="1" width="300">
<caption>人员表</caption>
<!--一个表中只有一个thead tfoot caption标签 但是可以有多个tbody-->
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>男</td>
<td>20</td>
</tr>
<tr>
<td>李四</td>
<td>男</td>
<td>20</td>
</tr>
<tr>
<td>李四</td>
<td>男</td>
<td>25</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
js代码
window.onload=function(){
//使用DOM来获取表格里边的数据
var table=document.getElementsByTagName('table')[0];
console.log(table.caption.innerHTML); //人员表
table.caption.innerHTML='该国'; //会改掉标题
console.log(table.tBodies[0]); //获取tbidy
console.log(table.rows.length); //4 tr 的行数
// table.deleteCaption(); //删除标题
// table.tBodies[0].deleteRow(0); //删除第一行
table.tBodies[0].rows[0].deleteCell(2); //删除第一行的3列
//使用DOM来创建表格 利用的是table的独特的方法
var tablenew=document.createElement('table');
tablenew.border=1;
tablenew.width=300;
tablenew.createCaption().innerHTML='热饿哇塞';
var thead=tablenew.createTHead();
var tr=thead.insertRow(0);
tr.insertCell(0).innerHTML='姓名';
tr.insertCell(1).innerHTML='性别';
tr.insertCell(0).innerHTML='年龄';
document.body.appendChild(tablenew);
}
,因为各个浏览器对css的支持能力不同,所以在使用js改变样式的时候要首先检测浏览器对css的支持
window.onload=function(){
alert(document.implementation.hasFeature('CSS','3.0')) //但是ie不会支持
}
引入样式的方法:
行内 元素的style属性添加的样式,
内联 在style标签里边书写的样式
链接 通过link链接到的样式
html代码
<div id="box" style="color:green;background: red">测试DIV</div>
js代码
window.onload=function(){
var box=document.getElementById('box');
//console.log(box.style); //返回的是样式一个对象
console.log(box.style.fontSize); //必须写成是驼峰式
box.style.fontWeight='bold'; //js改变字的粗细
console.log(box.style.cssText); //查看css文本
box.style.setProperty('height','300px'); //为style添加属性
box.style.removeProperty('height'); //为style移除属性
}
但是以上获取的style只能获取到行内样式,不能获取到内联和链接的样式。
取得浏览器给元素添加的默认的样式
window.getComputedStyle(box,null); //非IE
box.currentStyle //IE
window.onload=function(){
var box=document.getElementById('box');
var style=window.getComputedStyle(box,null); //第一个参数为对应的对象,第二个参数为伪类没有的话传null
console.log(style.fontSize); //默认为14px
//IE下得到浏览器默认的样式
var styleIE=box.currentStyle;
//跨浏览器获取计算后的样式
var stylenew=window.getComputedStyle?window.getComputedStyle(box,null):null||box.currentStyle;
console.log(styleIE.color);
}
计算后的样式 默认+给定的 这种方式可以获取到内联和链接的样式,但是这种不能赋值
对计算后的style进行获取,添加和删除
window.onload=function(){
//检测是否支持连接式,内联式样式表
//alert(document.implementation.hasFeature('StyleSheets','2.0')); //IE不支持
//获取link样式表
var link=document.getElementsByTagName('link')[0];
//var sheet=link.sheet; //表示链接的css样式表对象 IE不兼容
//为了兼容IE
var sheet=link.sheet||link.styleSheet;
alert(sheet); //返回的是一个CSSStyleSheet
}
得到
操作样式表
通过调用className,来改变样式。而且class调用时可以叠加的
叠加的意思:样式相同后边的会覆盖前边的,不同的话就添加属性
在以前的类上基础上添加新的类:自定义方法来实现
html代码
<div id="box" style="color:green;background: red;" class="aaa">测试DIV</div>
js代码
//element有这个类名cName,返回true else返回false
//!!作用是转化为布尔值
function hasClass(element,cName){
return !!element.className.match(new RegExp('(\\s|^)'+cName+'(\\s|$)'));
}
function addClass(element,cName){
if(hasClass(element,cName)===false){
element.className+=" "+cName;
}
}
function removeClass(element,cName){
if(hasClass(element,cName)===true){
element.className=element.className.replace(new RegExp('(\\s|^)'+cName+'(\\s|$)')," ");
}
}
window.onload=function(){
var bb=document.getElementById('box');
addClass(bb,'ssss');
addClass(bb,'ssss');
removeClass(bb,'aaa');
}
行内样式和链接样式(内联样式的得到方式不相同)
window.onload=function(){
var box=document.getElementById('box');
//跨浏览器获取内联或者链接的样式表
var stylenew=window.getComputedStyle?window.getComputedStyle(box,null):null||box.currentStyle;
console.log(stylenew.width); //200px;
//原生的window对象的style属性只能访问到行内样式,访问不到链接或者内联的样式
console.log(box.style.width); //由于width是链接里边的样式,所以不会输出
}
得到外部链接的样式的另一种方式
在css样式表中
#box{ width: 200px;background: red; }
js代码
window.onload=function(){
var box=document.getElementById('box');
var sheet=document.styleSheets[0];
var rule=(sheet.cssRules||sheet.rules)[0]; //得到的是style.css中的第一条样式
console.log(rule.style.width); //200px
console.log(rule.style.background); //red
}
注意:以上这种得到width的方式智能获得的设置时的大小,并不是元素实际的大小
样式表只是能获取到元素在样式表里边设置的大小,并不是本身的实际的大小。
获取元素的实际的大小
clientWidth 返回的数据类型是number 而且他不是style对象里边封装的,而是元素的一个特性
window.onload=function(){
var box=document.getElementById('box');
var sheet=document.styleSheets[0];
var rule=(sheet.cssRules||sheet.rules)[0]; //得到的是style.css中的第一条样式
console.log(rule.style.width); //200px
console.log(box.clientWidth); //600 没有单位 默认是px
//如果设置了其他的单位,自动会默认转换为px'
}
注意:增加外边框和边框之后不会增大clientWidth的值,就是说clientWidth不包括边框和外边距,但是会算上内边距的。增加滚动条后,这个值会减去滚动条的大小
scrollWidth 一般用于有溢出得到时候
window.onload=function(){
var box=document.getElementById('box');
console.log(box.clientWidth); //583=600-滚动条的宽
console.log(box.scrollWidth); //583=600-滚动条的宽
console.log(box.clientHeight); //483 显示的是滚动内容可见的一部分的高度
console.log(box.scrollHeight); //850 显示的是真是的高度
}
offsetWidth 获得的是元素实际的大小包括 内边距和外边距以及边框
window.onload=function(){
var box=document.getElementById('box');
console.log(box.clientWidth); //583=600-滚动条的宽
console.log(box.scrollWidth); //583=600-滚动条的宽
console.log(box.clientHeight); //483 显示的是滚动内容可见的一部分的高度
console.log(box.offsetWidth); //600 这就是元素的实际的宽度
console.log(box.scrollHeight); //850 显示的是真是的高度
}
获取元素周边元素的大小
offsetTop:当前元素相对于父元素的位置
clientLeft:边框的大小
style.css
#box{ width: 200px;background: red;padding: 200px;overflow: scroll;height: 100px;border:10px solid #ddd;position: absolute; top: 50px; }
js代码
window.onload=function(){
var box=document.getElementById('box');
console.log(box.clientLeft); //10
console.log(box.clientTop); //10
console.log(box.offsetTop); //50
}
scrollTop 溢出的时候 需要显示下边,上边隐藏掉的高度
window.onload=function(){
var box=document.getElementById('box');
console.log(box.scrollLeft); //10
console.log(box.scrollTop); //输出的是需要显示下边,上边隐藏掉的高度
if(box.scrollTop!=0){
box.scrollTop=10;
}
}
网站需求变大,脚本的需求也逐步变大,我们就不得不引入太多的js脚本而降低了整站的性能,所以就出现了动态加载脚本的概念
动态加载js脚本文件
window.onload=function(){
console.log(typeof BrowserDetect );
}
//必须是加载完成后页面中才会加载browserdetect这个js文件
var flag=true;
if(flag){
loadscript('js/browserdetect.js');
}
function loadscript(url){
//创建script标签
var script=document.createElement('script');
//为script添加属性
script.type='text/javascript';
script.src=url;
document.getElementsByTagName('head')[0].appendChild(script);
}
动态执行js脚本语句
window.onload=function(){
console.log(typeof BrowserDetect );
}
//必须是加载完成后页面中才会加载browserdetect这个js文件
var flag=true;
if(flag){
var script=document.createElement('script');
script.type='text/javascript';
script.appendChild(document.createTextNode('alert(100)')); //浏览器会弹出100
document.getElementsByTagName('head')[0].appendChild(script);
}
动态加载css样式表
window.onload=function(){
}
//必须是加载完成后页面中才会加载browserdetect这个js文件
var flag=true;
if(flag){
loadcss('css/style.css');
}
function loadcss(url){
//创建script标签
var link=document.createElement('link');
//为script添加属性
link.rel='stylesheet';
link.href=url;
document.getElementsByTagName('head')[0].appendChild(link);
}
动态执行style
window.onload=function(){
}
//必须是加载完成后页面中才会加载browserdetect这个js文件
var flag=true;
if(flag){
var style=document.createElement('style');
style.appendChild(document.createTextNode('#box{color:yellow}'));
document.getElementsByTagName('head')[0].appendChild(style);
}
事件一般适用于浏览器和用户进行操作和交互。
js中有三种事件模型 内联模型 脚本模型 DOM2模型
内敛模型:
这种模型是最早的一种事件处理的方法,在内联模型中,事件处理函数是html标签的一个属性,但是它并没有与html分离。
脚本模型
对象.事件=事件处理程序 一定不能加(), 事件处理程序只是一个函数的名字
window.onload=function(){
var box=document.getElementById('box');
box.onmousedown=function(){ //鼠标一按就会触发
console.log('mousedown')
};
box.click=function(){
console.log('mouseclick')
};
box.onmouseover=function(){
console.log('mouseover')
};
box.onmouseout=function(){
console.log('mouseout')
}
}
window的事件
加载的时候 onload、
html代码
<input type="text">
js代码
window.onload=function(){
var ii=document.getElementsByTagName('input')[0];
ii.onselect=function(){
alert(1); //当用户选择输入框中的文字的时候,会弹出1
}
}
事件的组成 三部分组成:对象.事件处理函数=函数。例如:单击文档任意处
document.onclick= function () {
alert(‘Lee’);
};
PS:以上程序的名词解释: click表示一个事件类型,单击。 onclick表示一个事件处理
函数或绑定对象的属性(或者叫事件监听器、 侦听器)。 document表示一个绑定的对象, 用于
触发某个元素区域。 function()匿名函数是被执行的函数,用于触发后执行。
this关键字和上下文
var input = document.getElementsByTagName('input')[0];
input.onclick= function () {
alert(this.value); //HTMLInputElement, this表示 input对象代表的是上下文
};
事件对象:触发某个事件时,会产生一个事件对象,这个对象包含着所有与事件有关的信息。
某个事件:这个对象是浏览器通过函数把这个对象(事件对象)作为参数传递过来的
实例解说事件对象
window.onload=function(){
document.onclick=bb.box; //二行会会输出MouseEvent
document.onkeydown=bb.box; //二行会会输出KeyboardEvent
}
var bb={
box: function(e){
console.log(arguments.length); //1
console.log(arguments[0]); //事件处理的函数,浏览器会默认传递一个参数,这个参数就是事件对象
//但是这个对象需要做一个兼容
var event=e||window.event; //w3c或者IE
console.log(e) //传进来的这个参数e就相当于arguments[0]
}
}
鼠标事件对象的属性
button 判断点了鼠标的那个键
IE下的Button属性的值
视区及屏幕坐标
事件对象提供了两组来获取浏览器坐标的属性, 一组是页面可视区左边, 另一组是屏幕坐标
当浏览器缩小时,测试者两个属性
window.onload=function(){
document.onmousedown=bb.box; //二行会会输出MouseEvent
}
var bb={
box: function(e){
var event=e||window.event;
console.log(event.clientX) //可视区 就是相对于浏览器
console.log(event.clientY)
console.log(event.screenX) //相对于整个屏幕
console.log(event.screenY)
}
}
修改键
window.onload=function(){
document.onkeydown=bb.box; //二行会会输出MouseEvent
}
var bb={
box: function(e){
var event=e||window.event;
console.log(event.shiftKey) //是否按下shift
}
}
键盘对象的属性
键码:keydown和keyup keyCode
keyCode属性的值与 ASCII码中对应小写字母或数字的编码相同。字母中大小写不影响
keyCode用在keydown
window.onload=function(){
document.onkeydown=bb.box; //二行会会输出MouseEvent
}
var bb={
box: function(e){
var event=e||window.event;
console.log(event.keyCode) //键盘上任意键的编码,而且字母不区分大小写
}
}
keyCode用在keypress 字符键 字母数字 但是shift、ctrl、alt键不是字母键
window.onload=function(){
document.onkeypress=bb.box; //二行会会输出MouseEvent
}
var bb={
box: function(e){
var event=e||window.event;
console.log(event.keyCode) //只返回键盘上的字母的编码 区分大小写
}
}
跨浏览器获得按下键盘的键盘编码
function getCharCode(evt) {
var e = evt || window.event;
if (typeof e.charCode== 'number') {
returne.charCode;
} else {
returne.keyCode;
}
}
获取事件目标 event.target||event.srcElement;
window.onload=function(){
var box=document.getElementById('box');
box.onclick=bb.box;
}
var bb={
box: function(e){
var event=e||window.event;
//兼容性的获取事件目标
var target= event.target||event.srcElement;
console.log(target) //会输出你点击的那个div 但是IE不支持这个属性
}
}
事件流:事件流是描述的从页面接受事件的顺序,几个都具有事件的元素层叠在一起的时候,那么你点击其中一个元素, 并不是只有当前被点击的元素会触发事件, 而层叠在你点击范围的所有元素都会触发事件。事件流包括两种模式:冒泡和捕获。
事件冒泡: 是从里往外逐个触发。
事件捕获:是从外往里逐个触发。
现在的浏览器要使用DOM2级模型的事件绑定机制才能手动定义事件流模式。
window.onload=function(){
document.onclick=function(){
console.log('documnet');
};
document.documentElement.onclick=function(){
console.log('html');
}
document.body.onclick=function(){
console.log('body');
}
document.getElementById('box').onclick=function(e){
console.log('box'); //点击div时 上边的都会输出 从里向外依次触发 默认是冒泡的
var event=e||window.event;
//event.stopPropagation(); //W3C对div上的事件取消冒泡
event.cancelBubble=true; //IE对div上的事件取消冒泡
}
}
传统绑定:window.onload=function(){}
传统绑定的一个弊端 后边定义的事件处理程序会覆盖掉前边的事件处理程序
window.onload=function(){
document.getElementById('box').onclick=function(e){
console.log('box');
}
}
//会覆盖掉第一个onload事件的处理程。
//解决方案:先检测window.onload是否存在 typeof window.onload
window.onload=function(){
}
用传统的事件绑定机制做一个事件切换器
window.onload=function(){
document.getElementById('box').onclick=toBlue;
}
function toBlue(){
this.className='blue';
this.onclick=toRed;
console.log(111);
}
function toRed(){
this.className='red';
this.onclick=toBlue;
}
注意:通过匿名函数执行一个函数,那么这个被执行函数里边的this就是window对象,
window.onload=function(){
var bb=document.getElementById('box');
bb.onclick=function(){
//但是这个输出语句智能执行一次,因为this.onclick=toBlue;会把bb.onclick=function()覆盖掉
console.log(this);
//通过匿名函数执行一个函数,那么这个被执行函数里边的this就是window对象,所以需要传递当前的this进去
toBlue.call(this);
}
}
function toBlue(){
this.className='blue';
this.onclick=toRed;
}
function toRed(){
this.className='red';
this.onclick=toBlue;
}
综上所述传统的绑定有如下3个问题:
1、后边的方法会覆盖掉前边的方法
2、对一个事件进行多种处理,会造成代码混乱
3、this的混乱
注意:window.onload=window[‘onload’];
克服传统事件绑定弊端的一个添加事件的函数
function addEvent(obj,type,fn){
var saved=null;
if(typeof obj['on'+type]=='function'){
saved=obj['on'+type]; //保存上一个事件
}
if(saved) saved();
fn();
}
addEvent(window,'load',function(){
console.log(122);
})
addEvent(window,'load',function(){
console.log(123);
})
addEvent(window,'load',function(){
console.log(124);
})
利用上边的函数实现事件切换器
function addEvent(obj,type,fn){
var saved=null;
if(typeof obj['on'+type]=='function'){
saved=obj['on'+type]; //保存上一个事件
}
if(saved) saved();
fn.call(this);
}
addEvent(window,'load',function(){
var box=document.getElementById('box');
addEvent(box,'click',toBlue)
})
function toBlue(){
this.className='blue';
this.onclick=toRed;
}
function toRed(){
this.className='red';
this.onclick=toBlue;
}
没有实现,但是不知道为什么,
注意:用完的事件就要移除掉,
function addEvent(obj,type,fn){
var saved=null;
if(typeof obj['on'+type]=='function'){
saved=obj['on'+type]; //保存上一个事件
}
if(saved) saved();
fn.call(this);
}
function removeEvent(obj,type){
//删除所有的
if(obj['on'+type]) obj['on'+type]=null;
}
addEvent(window,'load',function(){
var box=document.getElementById('box');
addEvent(box,'click',toBlue)
})
function toBlue(){
this.className='blue';
removeEvent(this,'click');
this.onclick=toRed;
}
function toRed(){
this.className='red';
removeEvent(this,'click');
this.onclick=toBlue;
}
但是以上这种删除时删除所有的click事件。这样就会导致误删掉很多事件,
W3C事件绑定:DOM2级事件” 定义了两个方法,用于添加事件和删除事件处理程序的操作:
addEventListener()和removeEventListener(),有DOM节点中都包含这两个方法,并且它
们都接受3个参数;事件名、函数、冒泡或捕获的布尔值(true表示捕获, false表示冒泡
一般来说都会传递false,因为IE都不支持捕获,考虑到兼容也要应该都传递false
这两个函数解决了传统绑定带来的问题:
1、不会覆盖 运行程序会一次输出111 222 333
window.addEventListener('load',function(){console.log(111)},false)
window.addEventListener('load',function(){console.log(222)},false)
window.addEventListener('load',function(){console.log(333)},false)
2、相同函数屏蔽的问题(这种问题可能是程序员忘了之前写过,又写一遍造成的)
window.addEventListener('load',aa,false);
window.addEventListener('load',aa,false);
function aa(){console.log(111)}
运行上面的代码,只会输出一次
3、可以传递this,不会造成this指针的混乱
window.addEventListener('load',function(){
var bb=document.getElementById('box');
bb.addEventListener('click',toRed,false) //不需要再.call()
},false);
function toBlue(){
this.className='blue';
this.removeEventListener('click',toBlue,false)
this.addEventListener('click',toRed,false)
}
function toRed(){
this.className='red';
this.removeEventListener('click',toRed,false)
this.addEventListener('click',toBlue,false)
}
W3C事件绑定很好的解决了事件绑定和删除,但是IE9以下不是完全支持,IE9就都支持了
W3C可以设置冒泡或者捕获的方式
window.addEventListener('load',function(){
var box=document.getElementById('box')
document.addEventListener('click',function(){
console.log('document');
},true); //把布尔值设置成true,则为捕获
box.addEventListener('click',function(){
console.log('Lee');
},true)
},true);
冒泡和捕获的区别:
设置为true的时候就是为捕获 点击box的时候,先输出document再输出 lee
设置为true的时候就是为捕获 点击box的时候,先输出lee再输出 document
和点击最外边的document并没有关系
现在的浏览器基本上都在IE9以上了,没有必要研究
得到最近移入移出的对象 relatedTarget
在W3C提供了一个属性: relatedTarget;这个属性可以在mouseover和mouseout事件
中获取从哪里移入和从哪里移出的DOM对象。
window.addEventListener('load',function(){
var box=document.getElementById('box');
box.addEventListener('mouseover',function(e){
console.log(e.relatedTarget); //移入时最近的那个元素
})
box.addEventListener('mouseout',function(e){
console.log(e.relatedTarget); //移出时最近的那个元素
})
},true);
阻止浏览器的默认行为 preventDefault
使用return false来阻止浏览器默认行为
window.addEventListener('load',function(){
var link=document.getElementsByTagName('a')[0];
link.onclick=function(){
return false;
}
//上面这种方式虽然可以阻止了浏览器的点击跳转行为,但是return语句必须放在最后,而且改成下边这种情况的时候就不会再起作用。
/*link.addEventListener('click',function(){
return false;
});*/
},true);
正确的阻止浏览器的默认行为
window.addEventListener('load',function(){
var link=document.getElementsByTagName('a')[0];
link.onclick=function(e){
var event=e||windwo.event
event.preventDefault(); //W3C下阻止浏览器的默认行为
}
link.onclick=function(e){
var event=e||windwo.event
event.returnValue=false //IE下阻止浏览器的默认行为
}
},true);
跨浏览器阻止浏览器默认行为
function preDef(evt) {
var e = evt || window.event;
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue= false;
}
}
上下文菜单事件: contextmenu,
我们右击网页的时候,会自动出现 windows自带的菜单。 那么我们可以使用 contextmenu事件来修改我们指定的菜单, 但前提是把右击的默认行为取消。
window.addEventListener('load',function(){
var bb=document.getElementById('box');
bb.addEventListener('contextmenu',function(e){
var event=e||window.event;
//先阻止了浏览器点击右键的默认行为
event.preventDefault();
var mm=document.getElementsByTagName('ul')[0];
mm.style.display='block';
mm.style.left=event.clientX+'px';
mm.style.top=event.clientY+'px';
document.addEventListener('click',function(){
mm.style.display='none';
},false);
},false)
},true);
右击div的时候会自定义的弹出菜单,
卸载前事件 beforeunload,在刷新或者离开页面的时候浏览器会弹出是否真的离开
window.addEventListener('beforeunload',function(e){
var ee=e||window.event;
ee.preventDefault();
},false)
但是没有实现
鼠标滚轮事件 这个事件区分的是火狐和非火狐,而不是w3c和IE
实现跨浏览器检测鼠标滚动事件
document.addEventListener('mousewheel',function(e){
alert(getDW(e));
},false)
document.addEventListener('DOMMouseScroll',function(e){
alert(getDW(e));
},false)
function getDW(e){
var ee=e||window.event;
if(ee.wheelDelta){
return ee.wheelDelta;
}
else if(ee.detail){
return -ee.detail*30;
}
}
早期js的功能:为了分担服务器处理表单的压力, JavaScript提供了一些解决方案,从而大大打破了处处依赖服务器的局面
html中标签来实现的,
在 JavaScript中,表单对应的则是HTMLFormElement类型。 HTMLFormElement继承了HTMLElement,
获取程序中的form表单对象的方法:
1、通过id获取
2、通过form这个标签类获取
3、通过document.forms[0]
4、通过document.forms[‘name’]
阻止提交按钮的默认的提交行为
注意:submit事件,需要用form对象来触发,为什么不是submit本身来绑定一个阻止事件呢?
这里实验证明,把submit事件注册到input中的submit按钮,是无法触发submit事件的,必须把submit事件绑定到form上菜可以触发submit事件
为不能提交的按钮添加提交的方法 submit
window.addEventListener('load',function(){
var myform=document.getElementById('myform');
var bb=document.getElementById('button');
bb.addEventListener('click',myform.submit,false); //为本身不能提交的按钮添加了提交的方法
},false);
注意:使用这个方法的时候必须是一个表单对象的submit方法
实现按下ctrl+enter实现提交
window.addEventListener('load',function(){
var myform=document.getElementById('myform');
document.addEventListener('keydown',function(ee){
var e=ee||window.event;
if(e.ctrlKey && e.keyCode==13){
myform.submit();
}
},false); //为本身不能提交的按钮添加了提交的方法
},false);
在表单中尽量避免使用name=”submit”或id=”submit”等命名,这会和submit()方法
发生冲突导致无法提交。
防止重复提交表单
提交数据最大的问题就是重复提交表单
1、放置通过提交按钮来多次提交数据
html代码
<form id="myform" name="yourname" >
<input type="text" name="user">
<input type="submit" value="提交" id="ss">
</form>
js代码
window.addEventListener('load',function(){
var myform=document.getElementById('myform');
var ss=document.getElementById('ss');
myform.addEventListener('submit',function(ee){
preDef(ee);
ss.disabled=true;
setTimeout(function(){
myform.submit();
},3000)
},false); //为本身不能提交的按钮添加了提交的方法
},false);
2、设置一个监听器来实现防止重复提交
var flag=false;
window.addEventListener('load',function(){
var myform=document.getElementById('myform');
var ss=document.getElementById('ss');
myform.addEventListener('submit',function(ee){
preDef(ee);
if(flag){
return;
}
flag=true;
console.log(111);
setTimeout(function(){
myform.submit();
},3000)
},false); //为本身不能提交的按钮添加了提交的方法
},false);
运行之后:点击提交之后按钮在3秒之内是禁用的,在3秒之后,提交了数据。按钮可以使用
源头刷新
某些浏览器, F5只能起到缓存刷新的效果,有可能获取不到真正的源头更新的数据。那么使用ctrl+F5就可以把源头给刷出来
表单控件:form里面的input submit textArea select其实就是元素标签
使用htmlDOM来获取表单字段
html代码
<form id="myform" name="yourname" >
<p>sjaisa</p>
<input type="text" name="user">
<input type="submit" value="提交" id="ss">
<input type="radio" name="sex" >男
<input type="radio" name="sex" >女
<p>sjaisa</p>
</form>
js代码
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
console.log(fm.elements.length); //会弹出2
//通过htmlDOM得到表单控件的时候,非表单控件都会被忽略掉
console.log(fm.elements[0]);//会输出input而不是p
console.log( fm.elements['user']); //会返回的是一个对象,没有length
console.log(fm.elements['sex'].length); //2 会返回的是一个数组对象里面包含两个对象
},false);
共有的表单字段属性
共有的表单字段方法 focus blur
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
fm.elements['user'].focus(); //实现了在页面记载完成后就可以将焦点置于文本框内
},false);
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
fm.elements['user'].addEventListener('blur',function(){
console.log(111); //光标移除会输出111
},false)
fm.elements['user'].addEventListener('change',function(){
console.log(222);
},false) //222 111 在发生change的时候也发生了blur
},false);
两种文本框表单
1、
2、
文本框的选择
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
document.addEventListener('click',function(){
//value和defaultValue这两个属性都是htmlDOM中的而不是标准DOM中
console.log(fm.elements['user'].value);
console.log(fm.elements['user'].defaultValue);
fm.elements['user'].select();
fm.elements['user'].setSelectionRange(0,1);
},false)
},false)
文本框的过滤输入
1、静止或者屏蔽非数字键的输入,阻止非数字键的默认行为
2、验证后取消,你可以先输入非法字符,然后判断取消你刚输入的文本
方案1 实现
function getCharCode(evt) {
var e = evt || window.event;
if (typeof e.charCode== 'number') {
return e.charCode;
} else {
return e.keyCode;
}
}
function preDef(evt) {
var e = evt || window.event;
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue= false;
}
}
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
fm.elements[0].addEventListener('keypress',function(e){
var ee=window.event||e ;
var cc=getCharCode(e);
console.log(String.fromCharCode(cc));
if(!/\d/.test()){
preDef(ee);
}
},false);
},false)
阻止裁剪、复制和粘贴
如果要阻止裁剪、复制和粘贴,那么我们可以在剪贴板相关的事件上进行处理,JavaScript提供了六组剪贴板相关的事件。
function preDef(evt) {
var e = evt || window.event;
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue= false;
}
}
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
fm.elements[0].addEventListener('copy',function(){
console.log(11);
},false);
fm.elements[0].addEventListener('beforecopy',function(){
console.log(22);
},false); //复制的时候这个会先于copy执行
fm.elements[0].addEventListener('paste',function(ee){
preDef(ee); //会禁止掉往文本框里边粘贴内容
},false);
},false)
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
fm.elements[0].addEventListener('keyup',function(){
this.value=this.value.replace(/[^\d]/g,"");
},false);
},false)
自动切换焦点
html代码
<form id="myform" name="yourname" >
<input type="text" name="a" maxlength=1>
<input type="text" name="b" maxlength=2>
<input type="text" name="c" maxlength=3>
<p>sjaisa</p>
</form>
js代码
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
fm['a'].addEventListener('keyup',tabFoc,false);
fm['b'].addEventListener('keyup',tabFoc,false);
fm['c'].addEventListener('keyup',tabFoc,false);
function tabFoc(){
console.log(this.value.length);
console.log(this.maxLength);
if(this.value.length == this.maxLength){
console.log(32);
for(var i=0;i<fm.elements.length;i++){
if(fm.elements[i]==this){
fm.elements[i+1].focus();
return ;
}
}
}
}
},false)
html代码
<form id="myform" name="yourname" >
<!-- multiple="multiple"设置可以选择多个选项,size可以设置显示几条-->
<select id="city" name="city" >
<option value="上海V">上海t</option>
<option value="南京V">南京t</option>
<option value="北京V">北京t</option>
<option value="武汉V">武汉t</option>
</select>
<p class="cc"></p>
</form>
js代码
window.addEventListener('load',function(){
var fm=document.getElementById('myform');
var cc=document.getElementsByClassName('cc')[0];
var city=fm.elements['city'];
console.log(city.options.length); //4
console.log(city.options[0]); //上海
city.addEventListener('change',function(){
//city.options[this.selectedIndex].value得到的是选择的选择选项的值
//city.options[this.selectedIndex].text得到的是选择的文本的值
cc.innerHTML=city.options[this.selectedIndex].value+city.options[this.selectedIndex].text;
//设置某个选项自动为选中状态
city.selectedIndex=3;
//判断第1个选项是否被选中
if(this.options[1].selected==true){
console.log('选择正确');
}
},false)
//为city这个下拉框添加选项
var oo=new Option('天津v','天津t');
city.add(oo,0)
//移除选项
city.remove(3);
//移动city中选项的顺序
var bb=city.options[3];
city.insertBefore(bb,city[bb.index-1]);
},false)
ECMAScript第 3版为了解决这个问题引入了 try…catch和 throw语句以及一些错误类型,让开发人员更加适时的处理错误。浏览器的错误报告默认情况都是关闭着的。
try catch特点:
1、可以获取错误信息
2、可以避免浏览器控制台报错
3、可以让程序继续执行 最好使用 e中的message来打印错误信息
错误类型
执行代码时可能会发生的错误有很多种。每种错误都有对应的错误类型, ECMA-262定义了7种错误类型:
1.Error
2.EvalError //这个错误非常难产生
3.RangeError new Array(-5);
4.ReferenceError var bpx=x; 变量未定义
5.SyntaxError 语法错误
6.TypeError new 10 类型错误
7.URIError
我们要利用这些信息来更精确的处理错误
善用try catch
因为js是弱类型的解释语言。没有必要非得使用t c来捕获错误
cookie也叫 HTTPCookie, 最初是客户端与服务器端进行会话使用的。比如, 会员登录,
下次回访网站时无须登录了; 或者是购物车, 购买的商品没有及时付款, 过两天发现购物车
里还有之前的商品列表
cookie的组成
name=value; [expires=date]; [path=path]; [domain=somewhere.com]; [secure]
中括号是可选, name=value是必选
可以在火狐的 选项 隐私 删除单个cookie 弹出对话框里边的localhost里边会有
查看cookie
console.log( document.cookie);
向本地磁盘写入cookie
document.cookie='user=' +'juanjuan';
//为了避免出现中文乱码
document.cookie='user=' +encodeURIComponent('赵文娟');
document.cookie='name=' +encodeURIComponent('卷边');
console.log(decodeURIComponent(document.cookie));
失效时间 expire 默认是在会话结束的时候清除cookie
每个浏览器的cookie是各自独立的,是彼此共享的。各自删除,互不影响
var dd=new Date();
//为了避免出现中文乱码
dd.setDate(dd.getDate()+1);
document.cookie='user=' +encodeURIComponent('赵文娟')+';expires='+dd;
document.cookie='id=' +encodeURIComponent('赵文娟')+';expires='+dd;
清除cookie 将过期时间设置为当前时间的前一点
window.addEventListener('load',function(){
console.log( typeof document.cookie);
var dd=new Date();
//为了避免出现中文乱码
dd.setDate(dd.getDate()-1);
document.cookie='user=' +encodeURIComponent('赵文娟')+';expires='+dd;
console.log(document.cookie);
},false)
将对cookie的操作封装
cookie.js
//expirs是传递的一个日期,在这里是延迟了6天
function setCookie(name,value,expirs,path,domian,secure){
var myCookie=encodeURIComponent(name)+'='+encodeURIComponent(value);
if(expirs instanceof Date){
console.log(11)
expirs=formatDate(6); //延迟了6天
myCookie+=';expires='+expirs;
}
if(path){
myCookie+=';path='+path;
}
if(domian){
myCookie+=';domian='+domian;
}
if(secure){
myCookie+=';secure='+secure;
}
document.cookie=myCookie;
}
//这个函数是通过name来获取相对应的在cookie的值
function getCookieValue(name){
var cookieName=encodeURIComponent(name)+"=";
var cookieStart=document.cookie.indexOf(cookieName);
var cookieEnd=document.cookie.indexOf(';',cookieStart);
if(cookieEnd==-1){
cookieEnd=document.cookie.length;
}
var cookieValue=decodeURIComponent(document.cookie.substring(cookieName.length+cookieStart,cookieEnd));
return cookieValue;
}
function formatDate(day){
if(typeof day=='number'&& day>0){
var dd=new Date();
dd.setDate(dd.getDate()+day)
}
else {
throw newError('传递的 day必须是一个天数,必须比 0大');
}
return dd;
}
function unsetCookie(name) {
document.cookie = name +"= ; expires=" + new Date(0);
}
cookie虽然在持久保存客户端用户数据提供了方便, 分担了服务器存储的负担。但是还有很多局限性的
第一:每个特定的域名下最多生成 20个 cookie(根据不同的浏览器有所区别)
为了更好的兼容性,所以按照最低的要求来,也就是最多不得超过 20个 cookie
第二: cookie的最大大约为4096字节(4k), 为了更好的兼容性, 一般不能超过4095字
节即可。
第三: cookie存储在客户端的文本文件,所以特别重要和敏感的数据是不建议保存在
cookie的。比如银行卡号,用户密码等。
比较高版本的浏览器, JavaScript提供了 sessionStorage和 globalStorage。在 HTML5中提供了 localStorage来取代 globalStorage。而浏览器最低版本为:IE8+、Firefox3.5+、Chrome
4+和 Opera10.5+
HTML5 提供两种web存储方法,localStorage 与 sessionStorage
localStorage 与 sessionStorage 区别
localStorage没有过期时间,只要不clear或remove,数据会一直保存。
sessionStorage 针对一个session进行数据存储,生命周期与session相同,当用户关闭浏览器后,数据将被删除。
sessionStorge和localStorage
window.addEventListener('load',function(){
sessionStorage.setItem('name','问卷');
console.log(sessionStorage.getItem('name'));// 问卷
sessionStorage.removeItem('name');
console.log(sessionStorage.getItem('name')); //null
},false)
json:是一种结构化的数据表示方式
对json的两种操作:
对 JSON进行解析和序列化
JSON的语法可以表示三种类型的值:
1.简单值:可以在 JSON中表示字符串、数值、布尔值和 null。但 JSON不支持 JavaScript中的特殊值 undefined。 //00、 “Lee”
2.对象:顾名思义。
var box = {
name : ‘Lee’,
age : 100
};
3.数组:顾名思义。
正常的json表示的方式
{
"name" : "Lee", //使用双引号,否则转换会出错
"age" : 100
}
一般情况下,我们可以把JSON结构数据保存到一个文本文件里,然后通过XMLHttpRequest对象去加载它,得到这串结构数据字符串(XMLHttpRequest对象将在Aajx章节中详细探讨)。所以,我们可以模拟这种过程。
模拟加载json数据的过程
1、最初的解析方式 eval这种方式不安全
//为了起到模拟的效果
var box='[{"name":"a","age":1},{"name":"b","age":2}]';
//最初的解析方式,使用的是eval,但是这种方式不安全
var json_box=eval(box);
console.log(json_box[0].name);
2、版本较高的浏览器都支持的一种解析方式
var box='[{"name":"a","age":1},{"name":"b","age":2}]';
var json_box=JSON.parse(box);
console.log(json_box[0].name);
JSON.parse(json,function) json转化为原生的js代码
//为了起到模拟的效果
var box='[{"name":"a","age":1},{"name":"b","age":2}]';
//将函数作为第二换个参数传递给parse是用来改写原来的json数据
var json_box=JSON.parse(box,function (key,value){
if(key=='name'){
return 'Mu'+value;
}
else{
return value;
}
});
console.log(json_box[0].name); //Mua
JSON.stringify 将js代码转化为json数据 序列化js代码,并且实现数据的部分过滤
var box=[{name:'a',age:1,height:200},{name:'b',age:2,height:200}]; //JavaScript原生值
console.log(typeof box); //object
var json=JSON.stringify(box); //转换成JSON字符串
console.log(typeof json); // string 自动添加双引号
console.log(json); // 会自动为name age 添加双引号
//对json数据进行简单的过滤
var json1=JSON.stringify(box,['name','age']); //转换成JSON字符串 但是过滤掉了height
console.log(json1); // 会自动为name age 添加双引号没有了height
//对json数据进行复杂的过滤
var json2=JSON.stringify(box,function (key,value) {
if (key == 'name') {
return 'Mu' + value;
}
else {
return value;
}
}); //转换成JSON字符串 但是过滤掉了height
console.log(json2); // [{"name":"Mua","age":1,"height":200},{"name":"Mub","age":2,"height":200}]
//JSON.stringify也可以传递第三个参数,实现json数据的数据的缩进
ajax: Asynchronous JavaScript + XML的简写。异步的javascript
Ajax技术核心是 XMLHttpRequest对象(简称 XHR)
在node.js的环境下使用ajax,在testUpload的文件夹下 ajax文件
AJAX的作用
XHR的出现,提供了向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器获取更多的信息, 这就意味着, 用户只要触发某一事件, 在不刷新网页的情况下,更新服务器最新的数据
GET请求
GET请求是最常见的请求类型,最常用于向服务器查询某些信息。必要时,可以将查
询字符串参数追加到 URL的末尾,以便提交给服务器。
AJAX提交的数据默认的编码格式是utf-8