Javascript学习笔记(一)

属性操作

基本属性

HTML的属性操作:读、写
属性名:
属性值:

读操作:获取、找到
元素.属性名

写操作:“添加”、替换、修改
元素.属性名 = 新的值

oP.innerHTML:读取p里面所有的html代码

JS 不允许出现"-",所以padding-top --> paddingTop margin-left --> marginLeft

通过className可以给对象添加一个class
例:oP.className = '类名';

以下不能做为判断条件

  1. 所有的相对路径地址
    img、src、href
    除了这种 这是绝对地址img src='http://www.baidu.com/1.png'
  2. 颜色值:color: red #f00 rgb()
    innerHTML值
  3. 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():

  1. 如果是Boolean值,true和false将分别转换为1和0。
  2. 如果是数字值,只是简单的传入和返回。
  3. 如果是null值,返回0。
  4. 如果是undefined,返回NaN。
  5. 如果是字符串,遵循下列规则:

 1)如果是字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即“1”变成1,“123”会变成123,而“011”会变成11(前导的零被忽略了);
 2)如果字符串中包含有效的浮点格式,如“1.1”,则将其转换为对应的浮点数值(同样也会忽略前导零);
 3)如果字符串中包含有效的十六进制格式,例如"0xf",则将其他转换为相同大小的十进制整数值;
 4)如果字符串是空的(不包含任何字符),则将其转换为0;
 5)如果字符串中包含除上述格式之外的字符,则将其他转换成NaN.

  1. 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用的对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。

由于Number()函数在转换字符串时比较复杂而且不够合理,因此在处理整数的时候更常用的是parseInt()函数

parseInt():

在转换字符串时,更多的时看其是否符合数值模式。会忽略字符串前面的空格,直至找到第一个非空格字符

  1. 如果第一个字符不是数字字符或都负号,parseInt()就会返回NaN; 也就是说,用parseInt()转换空字符串会返回NaN。
  2. 如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。例如,"1234blue"会被转换为1234,因为"blue"会被完全忽略。类似地"22.5"会被转换为22,因为小数点不是有效的数字字符。
  3. 如果字符串以"0x"开头且后跟数字字符,就会将其当作一个十六进制整数;
  4. 如果字符串以"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的数据类型:
数字、字符串、布尔、函数、对象、未定义

重用代码:

  1. 尽量保证 HTML 代码结构一致,可以通过父级选取子元素
  2. 把核心主程序实现,用函数包起来 即先现实一个,再重用
  3. 把每组里不同的值找出来,通过传参实现

作用域

什么是作用域:
:空间、范围、区域……
作用:读、写

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:返回值

  1. 函数名+括号:fn1() ==> return 后面的值;
  2. 所有函数默认返回值:未定义;
  3. 函数内,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('');
posted @ 2017-05-05 17:48  CHENJIAJIE  阅读(276)  评论(0编辑  收藏  举报