Javascript学习笔记(一)
属性操作
基本属性
HTML的属性操作:读、写
属性名:
属性值:
读操作:获取、找到
元素.属性名
写操作:“添加”、替换、修改
元素.属性名 = 新的值
oP.innerHTML:读取p里面所有的html代码
JS 不允许出现"-",所以padding-top --> paddingTop margin-left --> marginLeft
通过className可以给对象添加一个class
例:oP.className = '类名';
以下不能做为判断条件
- 所有的相对路径地址
img、src、href
除了这种 这是绝对地址img src='http://www.baidu.com/1.png' - 颜色值:color: red #f00 rgb()
innerHTML值 - checkbox和浮动兼容性小问题
IE6 IE7 IE8 不支持 oInp.type = 'checkbox';
兼容性解决:先把text隐藏掉,然后再显示checkbox;
用其他方式让视觉上看起来一样
js改元素浮动中,ie和非ie的方法不同
oDiv.style.float = 'right';
这个方法在好的浏览器的版本下支持,旧一点的浏览器不支持
兼容性解决
方法一:
兼容IE和非IE要写两条
IE:oDiv.style.styleFloat = 'right';
非IE:oDiv.style.cssFloat = 'left';
方法二:
可以通过在css上浮动然后再在js上赋给元素的方法实现
<div class="right"></div>
<style> .right{float:right;} </style>
<script> 元素.className = 'right' </ script>
push
往数组的最后一位添加"数据",同时数组长度变长
小细节
获取元素getElementById、getElementsByTagName
静态方法 getElementById(HTML没有写就找不到了)
#list {}
var oUl = document.getElementById('list');
动态方法 getElementsByTagName(HTML没有写就,但在js动态添加了也能找到)
li {}
var oLi = document.getElementsByTagName('li')[0];
#list li {}
var aLi = document.getElementsByTagName('li');
(注意Element后有 s 的,类似于数组)
for循环的性能问题
document.body.innerHTML += '<input type="button" value="按钮" />';
性能有问题
用上面的方法页面加载会慢,因为for循环一次就要到body读取一次innerHTML
应该用下面的方法,先加入到一个字符串,然后再把字符串赋给body.innerHTML
用 元素.length 时也一样,每循环一次就要计算一次长度,所以应该要先把长度存起来,var len = 元素.length
var str = '';
for( var i=0; i<6000; i++ ){
//document.body.innerHTML += '<input type="button" value="按钮" />';
str += '<input type="button" value="按钮" />';
}
document.body.innerHTML = str;
js写的样式是写到行间的,优先级最高
如果下面还有js改它的样式,则会覆盖行间样式,但不会影响内外部样式
this
this:指的是调用当前 方法(函数)的那个对象
function fn1(){
.....
}
fn1();//this => window
oDiv.onclick = fn1;//this => oDiv
oDiv.onclick = function (){
fn1();//fn1() 里的this => window
};
<div onclick="this fn1();"></div> //fn1(); 里的 this 指的是 window
alert( this );//object window
window 是 JS “老大”
自定义属性、索引值
JS可以为任何HTML元素添加任意个自定义属性
aBtn[0].abc = 123;//自定义属性
alert( aBtn[0].abc ); //123
aBtn[0].abc = 456;
配合this使用
aLi[i].onclick = function (){
if ( this.onOff ) {
this.style.background = 'url(img/active.png)';
this.onOff = false;
} else {
this.style.background = 'url(img/normal.png)';
this.onOff = true;
}
需要建立“匹配”“对应”关系,就用索引值this.index(自定义属性)
数据类型、类型转换
数据类型
ECMAScript:标准、核心
HTML 标签类型:block、inline、inline-block、table……
JS中的数据类型:数字、字符串、布尔、函数、对象(obj、[]、{}、null)、未定义
typeof() 判断数据类型
数据类型转换Number()、parseFloat()、parseInt()
显式类型转换(强制类型转换):
Number():可以用于任何数据类型转换成数值;
parseInt()、parseFloat():专门用于把字符串转换成数值;
parseInt():只有整数,小数点后不要
parseFloat():包括小数点后
转换规则:
Number():
- 如果是Boolean值,true和false将分别转换为1和0。
- 如果是数字值,只是简单的传入和返回。
- 如果是null值,返回0。
- 如果是undefined,返回NaN。
- 如果是字符串,遵循下列规则:
1)如果是字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即“1”变成1,“123”会变成123,而“011”会变成11(前导的零被忽略了);
2)如果字符串中包含有效的浮点格式,如“1.1”,则将其转换为对应的浮点数值(同样也会忽略前导零);
3)如果字符串中包含有效的十六进制格式,例如"0xf",则将其他转换为相同大小的十进制整数值;
4)如果字符串是空的(不包含任何字符),则将其转换为0;
5)如果字符串中包含除上述格式之外的字符,则将其他转换成NaN.
- 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用的对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。
由于Number()函数在转换字符串时比较复杂而且不够合理,因此在处理整数的时候更常用的是parseInt()函数。
parseInt():
在转换字符串时,更多的时看其是否符合数值模式。会忽略字符串前面的空格,直至找到第一个非空格字符。
- 如果第一个字符不是数字字符或都负号,parseInt()就会返回NaN; 也就是说,用parseInt()转换空字符串会返回NaN。
- 如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。例如,"1234blue"会被转换为1234,因为"blue"会被完全忽略。类似地"22.5"会被转换为22,因为小数点不是有效的数字字符。
- 如果字符串以"0x"开头且后跟数字字符,就会将其当作一个十六进制整数;
- 如果字符串以"0"开头且后跟数字字符,就会将其当作一个八进制整数;
parseInt()函数增加了第二参数用于指定转换时使用的基数(即多少进制)
如:
parseInt("10",16)//按十六进制解析;
parseInt("10",8)//按八进制解析
parseFloat():
与parseInt()函数类似,parseFloat()也是从第一个字符(位置0)形如解析每个字符,而且也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。
也就是说,字符串中的第一个小数点是有效的,而第二个小数点就是无效的了,因此它后面的字符串将被忽略。例如:"22.34.5"将会转换为22.34。
除了第一个小数点有效之外,parseFloat()与parseInt()的第二个区别在于它始终都会忽略前导的零。parseFloat()可以识别前面讨论过的所有的浮点数值格式,也包括十进制整数格式。但十六进制格式的字符串则始终会被转换成0。
由于parseFloat()只解析十进制值,因此它没有用第二个参数指定基数的用法。
另外,如果字符串包含的是一个可解析为整数的数(没有小数点,或者小数点后面都是零),parseFloat()会返回整数。
ex:
var num1=parseFloat("1234blue"); //1234
var num2=parseFloat("0xA");//0
var num3=parseFloat("0908.5");//908.5
var num4=parseFloat("3.125e7"); //31250000
注意:
1)值得注意的是,浮点数值的最高精度是17位小数,但在进行算术计算时其精确度远远不如整数。
例如
0.1加0.2的结果不是0.3,而是0.30000000000000004;
99.99加0.1的结果不是100.09而是100.08999999999999。
这个小小的舍人误差会导致无法测试特定的浮点数值。
ex.
if(a+b==0.3) //不要做这样的测试
2)在计算时有可能会计算出NaN的结果,ECMAScript定义了isNaN()函数。这个函数接受一个参数,该参数可以是任何类型,而函数会帮我们确定这个参数是否“不是数值”。isNaN()在接收到一个值之后,会尝试将这个值转换为数值。不能转换为数值的参数会返回true。
隐式数据转换
符号 | 例子 | 备注 |
---|---|---|
+ | 200 + '3' | 变成字符串 |
- * / % | '200' - 3 | 变成数字 |
++、 -- | 变成数字 | |
> < | 数字的比较 、字符串的比较 (按位比较,如'1000'<'9') |
|
! 取反 | 把右边的数据类型转成布尔值 | |
== |
和=的区别
==直接比较值,可能会把类型转换成一样的
===先比较类型再比较值
NaN()、isNaN()
NaN():not a number 不是一个数字 的 数字类型(也是属于数字类型)
一旦写程序中出现:NaN 肯定进行了非法的运算操作
NaN的布尔值是false
NaN()与自己都不相等
var a = Number('abc');
alert( a ); // NaN
alert( a === a ); // false
isNaN():Is not a number 是不是一个数字(不是数字)
判断某些值是不是数字
数字 =>false 非数字 =>true
内部会用Number()转换,看是不是数字类型,只要转换出来的是数字,则false,NaN则true
函数传参
函数传递参数
参数=JS的数据类型:
数字、字符串、布尔、函数、对象、未定义
重用代码:
- 尽量保证 HTML 代码结构一致,可以通过父级选取子元素
- 把核心主程序实现,用函数包起来 即先现实一个,再重用
- 把每组里不同的值找出来,通过传参实现
作用域
什么是作用域:
域:空间、范围、区域……
作用:读、写
script下定义的是全局变量、全局函数
一个一个域,先解析并执行,再到下一个域,自上而下
函数 :由里到外
浏览器:
“JS解析器”
1)“找一些东西”:var function 参数
a = ...
所有的变量,在正式运行代码之前,都提前赋了一个值:未定义 *(实际上不是赋值,只是识别到这个变量,因为没有赋值所以 未定义)
fn1 = function fn1(){ alert(2); }
所有的函数,在正式运行代码之前,都是整个函数块
这样叫JS 的预解析
遇到重名的:只留一个
变量和函数重名了,就只留下函数
2)逐行解读代码:
表达式:有这些东西的式子叫表达式= + - * / % ++ -- ! 参数……
表达式可以修改预解析的值!
ex:
alert(a);// function a (){ alert(4); } 预解释时的东西
var a = 1;
alert(a);// 1 执行var a = 1把1赋给a,把a的函数改为1了
function a (){ alert(2); }
alert(a);// 1 上一行函数声明并不能修改值
var a = 3;
alert(a);// 3
function a (){ alert(4); }
alert(a);// 3
alert( typeof a );
a();// 报错
ex1:
var a = 1;
function fn1(){
alert(a);// undefined
var a = 2;
}
fn1();
alert(a); // 1
ex2:
var a = 1;
function fn1(){
alert(a);// 1
a = 2;
}
fn1(); //执行到fn1函数时 ,在函数内部进行解析执行。预解析为空,没有var 函数声明等。执行alert(a) 输出的是1,因为函数会找上一级的预解析,这叫作用域链,由里到外往上爬,执行a = 2时同样先找自己的预解析,没有=> 找上一级的预解析,把上一级的a改为2了
alert(a); // 2
ex3:
var a = 1;
function fn1(a){ //有参数的函数相当于function fn1(var a = ?? ) 预解析会有var a ,与例子1一样
alert(a); // undefined
a = 2;
}
fn1();
alert(a); // 1
ex4:
var a = 1;
function fn1(a){
alert(a); // 1
a = 2;
}
fn1(a);
alert(a); // 1
运算符
真假的问题:数据类型-数字(NaN)、字符串、布尔、函数、对象(elem、[]、{}、null)、未定义
真:非0的数字、非空字符串、true、函数、能找到的元素、[]、{}
假:0、NaN、空字符串''、false、不能找到的元素、null、未定义
返回值、arguments、定时器、获取样式
返回值
return:返回值
- 函数名+括号:fn1() ==> return 后面的值;
- 所有函数默认返回值:未定义;
- 函数内,return 后面任何代码都不执行了;
arguments()
当函数的参数个数无法确定的时候:用 arguments
fn1( 1,2,3 ); // 实参——实际传递的参数
function fn1( a,b,c ){// 形参——形式上,abc代表123
function fn1(){ //不写形参,实参也会传入到函数内,会存在argument中
arguments => [ 1,2,3 ] —— 实参的集合
alert( arguments );
}
获取元素样式getComputedStyle(obj ).attr、obj.currentStyle.attr
getComputedStyle(obj ).attr (属性) ;// 适用于标准浏览器
obj.currentStyle.attr;// 适用于IE6 7 8
通过document.getElementById(id).style.XXX就可以获取到XXX的值,但意外的是,这样做只能取到通过内嵌方式设置的样式值,即style属性里面设置的值;
getComputedStyle方法获取的是最终应用在元素上的所有CSS属性对象(即使没有CSS代码,也会把默认的祖宗八代都显示出来);
getComputedStyle方法是只读的,只能获取样式,不能设置;而element.style能读能写,能屈能伸
兼容性解决(属性判断法):
obj.currentStyle ? obj.currentStyle.attr : getComputedStyle(obj).attr
注意:
- 想要BG颜色,不要直接获取,要用单一样式
background: url() red..... 复合样式
backgroundColor 单一样式
- 不要有空格
- 不要获取未设置的样式:不兼容
setInterval( 函数, 毫秒 )、setTimeout( 函数, 毫秒 )
定时器:时间概念
var timer = setInterval( 函数, 毫秒 );//重复执行
clearInterval( timer );
var timer = setTimeout( 函数, 毫秒 );//执行一次
clearTimeout( timer );
定时器管理、函数封装
无具体内容
获取系统时间new Date()
数字形式: new Date( 2013,4,1,9,48,12 );
字符串形式:new Date('June 10,2013 12:12:12');
ex:
var myTime = new Date();
// 下面这些的数据类型是 number
var iYear = myTime.getFullYear();
var iMonth = myTime.getMonth()+1;
//月份比较特殊,从零开始算
var iDate = myTime.getDate();
var iWeek = myTime.getDay();
var iHours = myTime.getHours();
var iMin = myTime.getMinutes();
var iSec = myTime.getSeconds();
var str = '';
//因为getday是数字,要转成文字
if( iWeek === 0 ) iWeek = '星期日';
if( iWeek === 1 ) iWeek = '星期一';
if( iWeek === 2 ) iWeek = '星期二';
if( iWeek === 3 ) iWeek = '星期三';
if( iWeek === 4 ) iWeek = '星期四';
if( iWeek === 5 ) iWeek = '星期五';
if( iWeek === 6 ) iWeek = '星期六';
公式:
天:Math.floor(t/86400)
时:Math.floor(t%86400/3600)
分:Math.floor(t%86400%3600/60)
秒:t%60
字符串方法
charCodeAt()、String.fromCharCode()
字符串中的空格也算一个字符;
charCodeAt():字符输入对应的unicode编码值
var str = ‘妙味课堂’
alert( str.charAt(0) ); //妙
alert( str.charAt(1) ); //味
alert( str.charCodeAt(0) );//22937输出的是计算机中,妙的unicode编码值
alert( str.charCodeAt(1) );//21613
String.fromCharCode():根据unicode编码值返回对应的字符
alert( String.fromCharCode(22937) );//妙根据unicode编码值返回一个汉字
alert( String.fromCharCode(22937,21619) );//妙味 这样可以得到两个字
数字字母对应的unicode
09-->4857
az-->97122
AZ-->6590
通过判断编码值知道字符是什么,由此选出合适的值。
小应用:给字符加密
可以用charCodeAt给字符转成编码,加减某个数后再用String.fromCharCode转回字符
indexOf()、lastIndexOf()
indexOf():从左往右寻找对应字符在字符串的位置
lastIndexOf():从右往左寻找对应字符在字符串的位置
var str = 'www.miaov.com/2013ww';
alert( str.indexOf('m') ); //4
alert( str.indexOf('m', 5) );//12 5表示从第五位开始找,若数字为负数则默认从第一位开始
alert( str.indexOf('X') ); // -1 表示没找到
比较类< > 、截取类substring()、slice()
< >:是按位比较的
alert( 'abbbbb' > 'b' );//false
alert( '10000' > '2' ); //false
alert( '10000' > 2 ); //true
< >在数字和字符比较时有一个强制类型转换,会把’10000’转换成数字10000
substring:截取字符串的一段
var str = '妙味课堂是一支独具特色的IT培训团队';
alert( str.substring(4) ); //是一支独具特色的IT培训团队一个参数就是截取到末尾
alert( str.substring(0,2) ); //妙味
alert( str.substring(2,0) ); //妙味 可以检测两个数,大的往后扔,小的往前扔
alert( str.substring(-3, 2) );//妙味 -3 负数当成0处理
alert( str.substring(2, -3) );//妙味 -3 当成0处理
slice:和substring一样,少了判断两个值大小自动换位置的功能,负数从后面倒着往前数
alert( str.slice( 2, 0 ) ); //不输出东西不交换位置
alert( str.slice( -4, -2 ) );//培训 负数从后面倒着往前数
toUpperCase()、toLowerCase()、split()、join()
toUpperCase:转成大写
toLowerCase:转成小写
只针对英文字母,判断时常用
split:拆分字符串并把字符串转成数组
var str = 'www.miaov.com';
alert( typeof str.split('.') );// [ 'www', 'miaov', 'com' ] 以 . 为界分割
var str1 = 'leo';
alert( typeof str1.split() );// [ 'leo' ] 没有分割符时,长度为一的数组
alert( str1.split('') );// [ 'l', 'e', 'o' ] 空字符时,把每个字符分开
var str3 = '/www.miaov.com/';
alert( str3.split('/').length );// [ , www.miaov.com, ] 分割符在头或尾,这种情况会有一个空的数组元素
var str4 = '2013-11-29-23-07';
alert( str4.split('-', 3) );//[ 2013, 11, 29] split第二个参数用来限制长度
join:拼接数组并把数组转成字符串
var arr = [ 'aa', 'bb', 'cc' ];
alert( arr.join() );//'aa'+','+'bb'+','+'cc' 长度为8的字符串
alert( arr.join('') );//aabbcc 把数组的元素直接拼在一块
alert( arr.join('-') ); //aa-bb-cc 有连接符时用连接符连接元素
应用在查找、替换的小功能上:
oP.innerHTML = oP.innerHTML.split(str).join('<span>'+str+'</span>');
相当于在str处拆开,然后加上<span>再拼起来
json一些概念、数组方法
json数据格式及语法
格式:
var json = { 'name' : 'leo', 'age' : 32 };
//这里json只是一个变量名,叫abc也可以的,这种形式的就叫json
这两种写法都可以:
var json2 = { name : 'miaov' };//相对不可靠
var json2 = { 'name' : 'miaov' };//推荐的,后端取到的数据可以安全稳定的转换出来,不会出现问题
读取:
json2.name ;
json2['name'] ; //第二种要有引号
改写:
json2.name = '妙味';
json2['name'] = 'miaov';
em.
var arrUrl = [ 'img/1.png', 'img/2.png', 'img/3.png', 'img/4.png' ];
var arrText = [ '小宠物', '图片二', '图片三', '面具' ];
上面两个数组就可以写成json形式
var imgData = {
url : [ 'img/1.png', 'img/2.png', 'img/3.png', 'img/4.png' ],
text : [ '小宠物', '图片二', '图片三', '面具' ]
};
数组里可以包json,json里可以包数组
[ {}, {}, {} ]
em.
var arr = [ { 'name' : 'TM', 'age' : 23 }, { 'name' : 'leo', 'age' : 32 } ]; //json可以没有名字的
alert( arr[0].name );//TM arr[0]就等于第0个json
alert( arr[1]['age'] );//32
for-in遍历json
var json4 = { 'name' : 'miaov', 'age' : 3, 'fun' : '前端开发' };
for ( var attr in json4 ) {
alert( attr );//读取的是属性名name、age、fun
alert( json4[attr] );//读取的是属性值miaov、3、前端开发
//[attr]不用引号
}
数组里包json或者json里包数组需要for-in和for嵌套
var json5 = {
'url' : [ 'img/1.png', 'img/2.png', 'img/3.png', 'img/4.png' ],
'text' : [ '小宠物', '图片二', '图片三', '面具' ]
};
for ( var attr in json5 ) {
for ( var i=0; i < json5[attr].length; i++ ) {
alert( json5[attr][i] );
}
}
for-in可以遍历json和数组,for循环只能用于数组
em.
var arr = [ 'a', 'b', 'c' ];
for ( var i in arr ) {
alert( arr[i] );
}
数组的定义
两种形式:
var arr = [ 1,2,3 ]; //更简便
var arr = new Array(1,2,3);
用new Array()时,如果值为一个数字时,会认为定义长度。
em.
var arr = new Array(1,2,3); //length = 3
var arr = new Array( 5 ); //length = 5
var arr = new Array(' 5 '); //length = 1
小细节
数组的length可以直接修改,后面的不要了
定义length = 0可以用来清空数组,直接重新定义新数组arr = []也可以;
但是字符串就不可以修改length
数字的添加删除方法push()、unshift()、pop()、shift()、splice()
push(): 从数组后面添加,同时返回数组新的长度
unshift():从数组前面添加,同时返回数组新的长度,但IE67不支持返回值
pop():从数组后面删除,同时返回被删除的值
shift():从数组前面删除,同时返回被删除的值
小技巧:
var arr = [ 'TM', '钟毅', '张森', '杜鹏', 'Leo' ];
arr.unshift(arr.pop()); //把数组最后的值放到最前
arr.push(arr.shift()) //把数组最前的值放到最后
splice():可以有删除、替换、添加的功能
应用:数组去重(方法有很多):
var arr = [ 1,2,2,4,2 ];
for ( var i=0; i<arr.length; i++ ) {
for ( var j=i+1; j<arr.length; j++ ) {
if ( arr[i] == arr[j] ) {
arr.splice( j, 1 );
j--;//因为判断完会j++,这样会跳过了一个
}
}
}
数组排序sort()
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
所以
var arr2 = [ 4,3,5,5,76,2,0,8 ];
arr2.sort();
alert( arr2 ); //0,2,3,4,5,5,76,8 按位比较
解决办法是用排序函数
如果想按照其他标准进行排序,就需要提供比较函数
sort()内置了排序函数
arr2.sort(function ( a, b ) {
return a - b; //正值不交换,从小到大排序
});
arr2.sort(function ( a, b ) {
return b - a; //负值交换,大到小
});
原理是随机选取数组的两个元素比较
元素不是数字的时候先转成数子
var arrWidth = [ '345px', '23px', '10px', '1000px' ];
arrWidth.sort(function ( a, b ) {
return parseInt(a) - parseInt(b);
});
alert( arrWidth );//比较时转成了数字,但是对原来的元素没有改变
另外自己可以写其他的算法
- 快速排序法
- 希尔(谢尔)排序法
- 冒泡排序法
- 归并排序法
- 选择排序法
- 插入排序法
应用:随机排序:
var arr = [ 1,2,3,4,5,6,7,8 ];
arr.sort(function ( a, b ) {
return Math.random() - 0.5;
});
原理:随机函数Math.random()是随机生成一个0到1的数字,减0.5就一会正数一会负数,所以a,b一会交换顺序一会不交换,就随机了
随机函数
Math.random() 方法可返回介于 0 ~ 1 之间的一个随机数。
Math.round() 方法可把一个数字舍入为最接近的整数。
随机返回0~10 的随机数:
Math.round(Math.random()*10)
随机返回5~10 的随机数:
Math.round( Math.random()*5 + 5 )
随机返回10~20 的随机数:
Math.round( Math.random()*10 + 10 )
随机返回20~100 的随机数:
Math.round( Math.random()*80 + 20 )
随机返回x ~ y 的随机数:
Math.round( Math.random()*(y-x) + x )
concat()、reverse()
concat() 方法用于连接两个或多个数组
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本
reverse() 方法用于颠倒数组中元素的顺序
上面两种方法都是用于数组的,当遇上字符串时,可以先用split()转成数组,最后再用join()转回数组
em.
var str = 'abcdef';
str.split('').reverse().join('');