JS (位运算符)

位运算符:

位运算符只针对数字的二进制形式进行。

var v1 = 5; //这是10进制,二进制其实是:101,在计算机内部其实类似这样: 00000101

var v2 = 6; //这是10进制,二进制其实是:110,在计算机内部其实类似这样: 00000110

按位与:

符号: &

含义:将两个二进制数字的对应位上的数字进行“与运算”,结果还是这些位运算的结果组成的二进制数所代表的值。

解释:二进制数字进行“与运算”的规则是:

1 & 1 è 1

1 & 0 è 0

0 & 1 è 0

0 & 0 è 0

举例:

var v1 = 5,  v2 = 6,运算图示为:

v1=5 0 0 0 0 0 1 0 1

v2=6 0 0 0 0 0 1 1 0

v1 & v2 0 0 0 0 0 1 0 0

var v3 = v1 & v2 = 00000100(2) = 4(10)

按位或:

符号: |

含义:将两个二进制数字的对应位上的数字进行“或运算”,结果是这些位运算的结果组成的二进制数所代表的值。

解释:二进制数字进行“或运算”的规则是:

1 | 1 è 1

1 | 0 è 1

0 | 1 è 1

0 | 0 è 0

按位非:

符号: ~ //这是一个“单目运算符”

含义:将一个二进制数字的对应位上的数字进行“非运算”,结果是这些二进制数字所代表的值。

解释:二进制数字进行“非运算”的规则是:

~1  è  0

~0  è  1

按位左移运算:

符号: <<

含义: 将一个二进制数的每一个位上的数字往左边移动指定的位数,并且左边“冒”出去的就不管了(不算了),右边空出来的位上填入“0”,得到的结果就是该二进制数字所代表的值。

举例:

var v1 = 5;var  v2 = 5 << 2; 运算图示为:

v1=5 0 0 0 0 0 1 0 1

v2= 5 << 2 0 0 0 1 0 1 0 0

var v2 = 5 << 2 = 00010100(2) = 1 * 24 + 1*22 = 16+4 = 20(10)

按位左移运算:

符号: >>

含义: 将一个二进制数的每一个位上的数字往右边移动指定的位数,并且右边“冒”出去的就不管了(不算了),左边空出来的位上填入原来的左边的数字,得到的结果就是该二进制数字所代表的值。

举例:

var v1 = 5;var  v2 = 5 >> 2; 运算图示为:

v1=5 0 0 0 0 0 1 0 1

v2= 5 >> 2 0 0 0 0 0 0 0 1

var v2 = 5 >> 2 = 00000001(2) = 1(10)

运算符其他内容:

赋值运算符:其实就一个基本的赋值运算符: = ,其含义是将等号右边的数据放到等号左边的变量中去。

错误的语法:

var v1 = 1,  v2 = 2,  v3 = 5,  v4 = -2;

v1 + v2 = v3 + v4; //错,大错,大错特错

复合赋值运算符: +=  -=  *=  /=  %=

运算符的优先级 —— 太多,较为复杂,记不住,但请记住一下几条规则:

1, 要心如明镜:运算符有优先级(先后顺序)问题。

2, 括号最优先,等号(赋值)最落后。

3, 先乘除后加减

4, 想不清楚或用不明白的,使用括号来解决

5, 括号只有小括号,可以一层层嵌套。

举例:

var  year = 2013;

//判断闰年:一个年份能被4整除并且不能被100整除是闰年,或者能被400整除,也是闰年。

if (  ( (year  %  4 == 0)  &&  (year % 100 != 0) )  ||  (year % 400 == 0)  )

{  documment.write(  year  + “是闰年”)  ;}

数据的传值方式:

var v1 = 10;

var v2 = v1;    //将v1中值拷贝一份,放到v2这个变量中去了——此时也可以说成“将v1的值传递给v2”

var v1 = v1 + v1;    //v1的值改变了,但并不影响v2——因为v2本身也是一个独立的变量。document.write(“<br/>v1=" + v1);        //20

document.write("<br/>v2=" + v2);        //10

上述“v2 = v1”就称为“拷贝传值”——取得v1的值并拷贝一份,然后赋值给v2

拷贝传值图示如下:

图片发自简书App

var v3 = {name:"小花", age:18, edu:"大学" };    //这是一个所谓“对象”类型——其中包括了3个数据。

//操作其中的数据类似这样:document.write("<br />v3这个对象的年龄为:" + v3.age);

v3.age = 19;  //v3这个对象的age这项数据的值重复赋了一个新值,类似前面v1 = 20;

var v4 = v3;    //此时,是将v3这个变量的“内存地址”传递给v4这个变量,而v3这个对象的数据本身其实只是由该地址来获取。——这就叫做引用传值——此时,其实这两个变量是一样的数据内容,类似一个人的多个名字:真名,艺名,网名,小名

document.write("<br />v4这个对象的年龄为:" + v4.age);

v3.age = 20;  //

document.write("<br />此时,v4这个对象的年龄为:" + v4.age);

图示:


注意: 基本(简单)数据类型的变量名和数据是直接存在“快速内存”(栈内存)中,而复合数据类型(对象和数组)的存储分两个部分:实际数据存在“慢速内存”(堆内存)中,栈内存中只存变量名和数据在堆内存中的位置(地址)。如图所示:

图片发自简书App

总结:        在js中,基本数据类型使用“拷贝传值”——传值的时候直接就出现了一份新的数据(当然同时也是另一个变量所代表)

      复合数据类型(数组和对象)使用“引用传值”——传值的时候只是做了一个地址指向,数据仍然只有一份,两个变量就指向这同一份数据。

if分支结构:

控制结构:就是使用一定的语法来控制我们程序执行的流程——也可以叫“流程控制结构”

分支就是“多条路径,走一条”。

最简形式:

//如果此条件满足(即条件判断的结果是true),则会执行其中的语句块,否则什么也不做。

if(  条件判断语句  )

{

//要执行的语句块——语句块其实就是一种表示“n条语句”泛泛说法。

}

二选一分支形式:含义是两条路,必走一条。

if(  条件判断语句  )

{

//要执行的语句块1——前面条件成立时执行

}

else

{

//要执行的语句块2——前面条件不成立时执行

}

多选一分支结构:多条路根据条件的满足情况走其中一条,但也可能一条都不走:

if(  条件判断1 ) //如果此条件满足,则执行语句块1,然后if就结束了

{

//语句块1

}

else  if ( 条件判断2  ) //如果条件1不满足,则判断条件2:如果满足,则执行语句块2,并结束if

{

//语句块2

}

else  if ( 条件判断3  ) //如果条件2不满足,则判断条件3:如果满足,则执行语句块3,并结束if

{

//语句块3

}

…………………… //依此类推。。。。。。如果没有一个条件满足,则其实到最后什么也不会执行,if结束。

综合型式:

if(  条件判断1 ) //如果此条件满足,则执行语句块1,然后if就结束了

{

//语句块1

}

else  if ( 条件判断2  ) //如果条件1不满足,则判断条件2:如果满足,则执行语句块2,并结束if

{

//语句块2

}

else  if ( 条件判断3  ) //如果条件2不满足,则判断条件3:如果满足,则执行语句块3,并结束if

{

//语句块3

}

…………….  //依此类推。。。。。。

else

{

//最后的else语句块。 //此语句块会在前面条件都不满足的时候去执行。

}

注意:综合型式中是必有一条分支(语句块)会得到执行。

switch分支结构:

switch的分支结构整体含义跟if类似,也是表示“多条路走一条”,其使用形式:

switch (  一个变量或表达式  ) //不管是变量还是表达式,最终都代表一个“值”,我们用v1来说话

{

case  固定值1: //如果v1等于本值1,则会执行语句块1

//语句块1;

break; //退出此switch结构

case  固定值2: 如果v1不等于前面值1,则继续判断是否等于这里的值2,如果相等,执行语句2

//语句块2;

break; //退出此switch结构

case  ………………………………

。。。。。。。。。。。。。。。。。

default: //如果前面各个判断都不成立(也就是不相等),则会执行此语句块。

//注意:switch中此default语句块可以没有。

//默认语句块

}

特别注意:if语句其实是可以使用非常灵活的条件判断,比如  >  >=  <  <=  ==  !=  ===  ,但,switch这里case的判断,只能有一种判断:相等判断。

while循环结构:

循环的基本观念:

1, 循环就是让某些程序(语句块)反复执行

2, 循环必须能够有办法停止——计算机没有自己的判断能力去决定“累了,不做了”

while循环的基本语法形式:

while  (  条件判断  ) //如果条件判断满足了,则会执行其中的语句块,否则while结束。

{

//要执行的语句块

} //如果此语句块执行完了,会立即回到前面while的位置继续判断。

上述形式只是语法上的基本要求,但,在“实用”中,通常会需要遵照如下模式:

【循环变量初始化】

while  (  【循环变量作为条件判断】 )

{

//循环体,就是要反复执行的语句块

【循环变量值的改变】

}

do while循环结构:

do while循环是一种会先执行一次,然后再根据判断条件来决定是否继续执行并循环的一种循环结构。

do while的实用形式如下:

【循环变量初始化】

do

{

//循环体,就是要反复执行的语句块

【循环变量值的改变】

} while  (  【循环变量作为条件判断】 ) ;

描述: 先执行do后面打括号中的语句块,然后再进行while语句中的条件判断,如果判断成立(true),则继续回到上面do后面的大括号中执行语句块,否则就结束。

for循环结构——推荐使用:

for循环基本形式:

for(  【循环变量初始化A】; 【循环变量作为条件判断B】; 【循环变量值的改变C】  )

{

//循环体D,也就是要反复执行的语句块

}

for循环的执行逻辑(顺序):

A  è  Bètrue  è D  è  C  è Bètrue  è D  è C  è Bè

  ┗èfalseèfor循环结束 ┗èfalseèfor循环结束

var a = new Date(); //new Date() 就是指“系统时间”,该时间其实就是一个“复合数据”,其中包括了时间(日期)中的各项值,比如年份数,月份数,时分秒,星期等等。其中每个数据都是一个“数字”而已。

var week = a.getDay(); //获取今天系统时间对应的星期,这里获取的星期只是一个0到6的数而已。0代表礼拜天,1代表礼拜一。

昨日回顾

位运算符:指对二进制数字进行的运算

按位左移:将所有数位往左边移动指定的位数,左边冒出去的不管,右边补0

按位右移:将所有数位往右边移动指定的位数,右边冒出去的不管,左边补原来左边的数字(0或1)

按位与:将两个二进制数字的对应位进行二进制数的“相与”(只有两个是1才是1)

按位或:将两个二进制数字的对应位进行二进制数的“相或”(只有两个是0才是0)

按位非:将一个二进制数字的每一位“取反”所得结果。

传值方式:指将一个变量(A)的值传给另一个变量(B)的时候的不同机制问题

拷贝传值:将变量A的值做一份“拷贝”,并赋值给另一个变量B——B和A此时是两个相互独立的变量,但此时的值相同(相等)——js中,基本数据类型使用拷贝传值。

引用传值:将变量A的实际数据的“地址”拷贝给变量B(并没有拷贝数据)——B和A是两个有关系的变量,即他们实际上就是指“一份数据”,类似“同样的内容不同的名字”——在js中,复合数据类型使用引用传值。

流程控制之 if  分支结构

if( 条件判断1 )

{

//语句块1

}

else  if( 条件判断2 )

{

//语句块2

}

else  if( 条件判断3 )

{

//语句块3

}

。。。。。。。。。。。。

else

{

//else语句块

}

流程控制之 switch 分支结构

switch (  一个变量或表达式  ) //这里最终都应该是一个“值”

{

case  值1:

语句块1

break;

case  值2:

语句块2

break;

。。。。。。。。。。。。。。。。。。

default:

默认语句块

}

流程控制之 while 循环结构

循环变量的初始化

while  (  循环变量判断 )

{

//语句块

循环变量的改变

}

流程控制之 do while 循环结构

循环变量的初始化

do

{

//语句块

循环变量的改变

}

while (  循环变量判断 );

流程控制之 for 循环结构

for(  循环变量的初始化;循环变量判断;循环变量的改变 )

{

//语句块

}

昨日回顾

位运算符:指对二进制数字进行的运算

按位左移:将所有数位往左边移动指定的位数,左边冒出去的不管,右边补0

按位右移:将所有数位往右边移动指定的位数,右边冒出去的不管,左边补原来左边的数字(0或1)

按位与:将两个二进制数字的对应位进行二进制数的“相与”(只有两个是1才是1)

按位或:将两个二进制数字的对应位进行二进制数的“相或”(只有两个是0才是0)

按位非:将一个二进制数字的每一位“取反”所得结果。

传值方式:指将一个变量(A)的值传给另一个变量(B)的时候的不同机制问题

拷贝传值:将变量A的值做一份“拷贝”,并赋值给另一个变量B——B和A此时是两个相互独立的变量,但此时的值相同(相等)——js中,基本数据类型使用拷贝传值。

引用传值:将变量A的实际数据的“地址”拷贝给变量B(并没有拷贝数据)——B和A是两个有关系的变量,即他们实际上就是指“一份数据”,类似“同样的内容不同的名字”——在js中,复合数据类型使用引用传值。

流程控制之 if  分支结构

if( 条件判断1 )

{

//语句块1

}

else  if( 条件判断2 )

{

//语句块2

}

else  if( 条件判断3 )

{

//语句块3

}

。。。。。。。。。。。。

else

{

//else语句块

}

流程控制之 switch 分支结构

switch (  一个变量或表达式  ) //这里最终都应该是一个“值”

{

case  值1:

语句块1

break;

case  值2:

语句块2

break;

。。。。。。。。。。。。。。。。。。

default:

默认语句块

}

流程控制之 while 循环结构

循环变量的初始化

while  (  循环变量判断 )

{

//语句块

循环变量的改变

}

流程控制之 do while 循环结构

循环变量的初始化

do

{

//语句块

循环变量的改变

}

while (  循环变量判断 );

流程控制之 for 循环结构

for(  循环变量的初始化;循环变量判断;循环变量的改变 )

{

//语句块

}

昨日回顾

位运算符:指对二进制数字进行的运算

按位左移:将所有数位往左边移动指定的位数,左边冒出去的不管,右边补0

按位右移:将所有数位往右边移动指定的位数,右边冒出去的不管,左边补原来左边的数字(0或1)

按位与:将两个二进制数字的对应位进行二进制数的“相与”(只有两个是1才是1)

按位或:将两个二进制数字的对应位进行二进制数的“相或”(只有两个是0才是0)

按位非:将一个二进制数字的每一位“取反”所得结果。

传值方式:指将一个变量(A)的值传给另一个变量(B)的时候的不同机制问题

拷贝传值:将变量A的值做一份“拷贝”,并赋值给另一个变量B——B和A此时是两个相互独立的变量,但此时的值相同(相等)——js中,基本数据类型使用拷贝传值。

引用传值:将变量A的实际数据的“地址”拷贝给变量B(并没有拷贝数据)——B和A是两个有关系的变量,即他们实际上就是指“一份数据”,类似“同样的内容不同的名字”——在js中,复合数据类型使用引用传值。

流程控制之 if  分支结构

if( 条件判断1 )

{

//语句块1

}

else  if( 条件判断2 )

{

//语句块2

}

else  if( 条件判断3 )

{

//语句块3

}

。。。。。。。。。。。。

else

{

//else语句块

}

流程控制之 switch 分支结构

switch (  一个变量或表达式  ) //这里最终都应该是一个“值”

{

case  值1:

语句块1

break;

case  值2:

语句块2

break;

。。。。。。。。。。。。。。。。。。

default:

默认语句块

}

流程控制之 while 循环结构

循环变量的初始化

while  (  循环变量判断 )

{

//语句块

循环变量的改变

}

流程控制之 do while 循环结构

循环变量的初始化

do

{

//语句块

循环变量的改变

}

while (  循环变量判断 );

流程控制之 for 循环结构

for(  循环变量的初始化;循环变量判断;循环变量的改变 )

{

//语句块

}