谓操作符,就是用来操作数据值的符号,在JavaScript中包括算术操作符、位操作符、关系操作符和相等操作符。这些操作符可以操作所有类型的数据,比如字符串、数字、布尔值,甚至对象。
所谓一元操作符就是只能对一个数据值进行操作,比如(递增、递减)操作符。
递增、递减操作符是直接借鉴C语言的,它分前置型和后置型。前置就是操作符在要操作的变量之前,后置在变量之后。
如下示例:
// 前置型
let age = 20;
++age; // 递增
console.log(age); // 结果输出21
--age;//递减
console.log(age); // 结果输出20
如上面例子,age通过++操作符递增变成21,又通过--操作符递减变成20;上面的操作等同下面的操作:
// 后置型
let age = 20;
age = age + 1; // 加1
age = age -1; // 减1
同理使用后置操作符会得到上面同样的结果,但是前置和后置有区别。前置操作符在语句被求值以前改变,后置是在语句被求值后改变。通过下面的例子看下其区别:
// 前置
let age = 20;
let anotherAge = --age + 5;
alert(age); // 输出19
alert(anotherAge); // 输出24
由于前置操作符的优先级和执行语句相等,因此会从左到右依次求值。上面的--age 会先进行递减操作,再继续后面的 + 5 运算,所以结果是24。
// 后置时
let age = 20;
let anotherAge = age-- + 5;
alert(age); // 输出19
alert(anotherAge); // 输出25
但是后置的最终结果却是25,因为age-- 使用了递减前的值继续和后面进行+5运算。
如果使用一个加号或减号时,加号代表正值、减号代表负值。
操作多个数据值,比如加减乘除等:
let a = 1,b=2;
let c = a + b; // 加
let d = c - a; // 减
let e = d * b; // 乘
let f = e/d; // 除
注意加减乘除主要用来操作数字类型的数据,如果操作数不是数字类型,会先进性强制转换再进行计算,这样结果会不确定。
位操作符,是指按内存中的表示的数值位来操作数值,通俗讲就是用来操作二进制的数据。二进制数据都是由0、1组成的,在JavaScript中所有数值都是64位的格式存储,但位操作符不直接在64位的值上进行计算,会先转化成32位后再运算。位操作符有以下几种:
按位非(NOT)
按位非操作符是(~)符号,就是将二进制中每位数值进行反码操作。其规则如下:
操作符 | 数值 | 结果 |
~ | 1 | 0 |
~ | 0 | 1 |
如下示例:
let a = 25;
let b = ~a;
alert(b); // 输出-26
按位与(AND)
使用(&)符号表示,它有2个操作数,当2个数对应的位都是1时返回1,任何一位是0则返回0。如下规则:
数值1 | 操作符 | 数值2 | 结果 |
1 | & | 1 | 1 |
1 | & | 0 | 0 |
0 | & | 1 | 0 |
0 | & | 0 | 0 |
示例:
let a = 25 & 3;
alert(a); // 输出结果是1
按位或(OR)
用(|)符号表示,同样也是2个操作数。其规则是只要有一位是1其结果就是1,负则结果是0;
数值1 | 操作符 | 数值2 | 结果 |
1 | | | 1 | 1 |
1 | | | 0 | 1 |
0 | | | 1 | 1 |
0 | | | 0 | 0 |
示例:
let a = 25 | 3;
alert(a); // 输出结果是27
按位异或(XOR)
由(^)符号表示,也是操作2个操作数,其当2个操作数的位值相同时返回0,负则返回1。
数值1 | 操作符 | 数值2 | 结果 |
1 | ^ | 1 | 0 |
1 | ^ | 0 | 1 |
0 | ^ | 1 | 1 |
0 | ^ | 0 | 0 |
示例:
let a = 25 ^ 3;
alert(a); // 输出结果是26
左移
使用(<<)两个小于号表示,这个操作符会将数值每一位向左移动指定位数。如下示例:
let a = 2; // 二进制 10
let b = b << 5; // 二进制的 1000000,十进制64
上面,将二进制10向左移动5位,注意左移会多出5个空位,用0来填充,这样就会得到一个完整的32位二进制数据。
注意,左移不会影响符号位(二进制位中第一位表示数的正负),如-2 向左移5位结果是-64。
有符号的右移
使用(>>)两个大于号表示,会将每位向右移动指定位数,但保留符号位(即正负号标记)。如下示例:
let a = 64; // 二进制 1000000
let b = b >> 5; // 二进制的 10,十进制的2
在移位过程,原数中也会出现空位,只不过这次空位出现在原数值左侧、符号位右侧。空位使用符号位值填充。
有符号的整数,指32位中前31位表示整数的值,第32位表示数值的符号,0正数,1负数。这个表示符号的位就是符号位。
无符号的右移
使用(>>>)三个大于号表示,这个操作会将所有32位都向右移动。对于正数其结果和有符号的右移一样,如下示例:
let a = 64; // 二进制 1000000
let b = b >>> 5; // 二进制的 10,十进制的2
但是负数就不一样了,无符号的右移是以0来填充空位,不像有符号右移使用符号位填充。所以其结果相差很大,如下示例:
let a = -64; // 二进制 1111 1111 1111 1111 1111 1111 1100 0000
let b = b >>> 5; // 二进制 0000 0111 1111 1111 1111 1111 1111 1110 ,十进制的134217726
在任何编程语言中,布尔操作符都是非常重要的,它是用来判断逻辑的关键,布尔操作符一共有三种:非(NOT)、与(AND)、或(OR)。
逻辑非
使用(!)感叹号表示逻辑非,其规则就是:
操作符 | 逻辑值 | 结果 |
! | true | false |
! | false | true |
逻辑与
使用(&&)表示,操作两个数,如下示例:
let a = ture && false;
其规则如下:
逻辑值1 | 操作符 | 逻辑值2 | 结果 |
ture | && | ture | ture |
ture | && | false | false |
false | && | ture | false |
false | && | false | false |
也就是只有当2个数值都是true时其结果才是true。
逻辑或
使用(||)符号表示,也是有两个操作数,其示例:
let a = true || false;
规则如下:
逻辑值1 | 操作符 | 逻辑值2 | 结果 |
ture | || | ture | ture |
ture | || | false | ture |
false | || | ture | ture |
false | || | false | false |
也就是2个操作数中有一个true,结果就是true,负则是false。
注意布尔操作符,不仅仅可以操作布尔类型值,对于其它数据类型同样适用,只不过会先将其它数据类型转换成布尔值,再进行布尔运算。如下示例:
let a = !1; // 输出false
let b = !'string'; // 输出false
let c = 1 || 0; // 输出true
let e = 1 && 0;// 输出false
let d = ''&& 2; // 输出true
关系操作符用来比较2个操作数,有小于(<)、大于(>)、小于等于(<=)和大于等于(>=)。其比较的结果返回一个布尔值,true或false。
如下示例:
let a = 5 > 3; // true
let b = 5 < 3; // false
同样,关系操作符也可以适用其它类型的数据,比如字符串比较大小时,会按照字符的编码大小比较。如下示例:
let a = "Brick" < "alphabet"; // true,
上面中因为B字符编码是66,a的编码是97,所以返回true。
在编程中,确定2个值是否相等是一个非常重要的操作。在JavaScript中分相等(==)和全等(===)、不等(!=)和不全等(!==)四种。
相等(==)和不相等(!=)
如下示例:
let a = 1 == 1; // true
let b = 1==0;// false
let c = 1!=1; // false
let d = 1!=0; //true
注意相等和不相等的操作前会先对操作性进行强制转换,如下示例:
let a = true == 1; // 先将true转换成1再比较,结果是true
let b = false == 1; // 先将false转换成0再比较,结果是false
全相等(===)和不全相等(!==)
全等和不全等不同之处是,它在比较数据前,不进行数据类型转换,是对原始数值比较,所以它的结果更加严格准确,如下示例:
let a = 1 === 1; // true
let b = 1=== '1';// false
let c = 1!==1; // false
let d = 1!=='1'; //true
注意和之前相等和不相等的例子比较,其结果非常不一样。
使用(=)表示赋值操作,其作用就是把等号右侧的值赋值给左边的变量或属性,如下示例:
let a = 10; // 给a变量赋值10
如果在等号前面加上其它操作符,就组成了复合型赋值操作,如下示例:
let a = 10;
a += 5; // 结果是 15
上面的等同于下面:
let a = 10;
a = a + 5; // 结果是 15
当然也可以使用其它操作符,如(*=)、(/=)、(%=)、(-=)、(<<=)等等。
也称三目运算符,它是一种简便的条件运算,可以把它看成是if else的简化,其语法如下:
变量 = 布尔表达式 ? true_value : false_value
先求出问号前面的布尔表示结果,如果是true,变量使用冒号前面的值,负则使用冒号后面的值。如下示例:
let a = 5 > 3 ? '好' : '不好'; // 结果是 '好'
使用(,)符号,表示可以执行多个操作,常用于变量定义或函数参数,如下示例:
var a = 0,b=1,c=2; // a、b、c使用逗号隔开
let a,b,c;
// 函数中的参数a、b、c使用逗号隔开
function test(a,b,c){
// 函数主体
}
// 调用函数
test(1,2,3)
本节主要讲述了JavaScript中所有的操作符概念,这些都是最基本的知识,需要完全掌握。在平常工作中其中除了位操作符不常用外,其它操作符使用频率很高,尤其是布尔操作符,算术操作符,比较操作符等。
本篇只是大概讲述了操作符的概念和使用方法,还有一些细节没有讲到,作为入门课程已经足够了,你可以自己搜索每个知识点详细内容,比如关于二进制数据、位操作、数据类型强制转换等,这里不再详细介绍。
《JavaScript 高级程序设计》
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
https://www.w3cschool.cn/javascript/js-operators.html
SS Padding(填充)属性定义元素边框与元素内容之间的空间。
Padding(填充)
当元素的 Padding(填充)(内边距)被清除时,所"释放"的区域将会受到元素背景颜色的填充。
单独使用填充属性可以改变上下左右的填充。缩写填充属性也可以使用,一旦改变一切都改变。
可能的值
值 | 说明 |
---|---|
length | 定义一个固定的填充(像素, pt, em,等) |
% | 使用百分比值定义一个填充 |
填充- 单边内边距属性
在CSS中,它可以指定不同的侧面不同的填充:
实例
padding-top:25px;
padding-bottom:25px;
padding-right:50px;
padding-left:50px;
填充 - 简写属性
为了缩短代码,它可以在一个属性中指定的所有填充属性。
这就是所谓的缩写属性。所有的填充属性的缩写属性是"padding":
实例
padding:25px 50px;
尝试一下 »
Padding属性,可以有一到四个值。
padding:25px 50px 75px 100px;
上填充为25px
右填充为50px
下填充为75px
左填充为100px
padding:25px 50px 75px;
上填充为25px
左右填充为50px
下填充为75px
padding:25px 50px;
上下填充为25px
左右填充为50px
padding:25px;
所有的填充都是25px
更多实例
在一个声明中的所有填充属性
这个例子演示了使用缩写属性设置在一个声明中的所有填充属性,可以有一到四个值。
设置左部填充
这个例子演示了如何设置元素左填充。
设置右部填充
这个例子演示了如何设置元素右填充。.
设置上部填充
这个例子演示了如何设置元素上填充。
设置下部填充
这个例子演示了如何设置元素下填充。
所有的CSS填充属性
属性 | 说明 |
---|---|
padding | 使用缩写属性设置在一个声明中的所有填充属性 |
padding-bottom | 设置元素的底部填充 |
padding-left | 设置元素的左部填充 |
padding-right | 设置元素的右部填充 |
padding-top | 设置元素的顶部填充 |
如您还有不明白的可以在下面与我留言或是与我探讨QQ群308855039,我们一起飞!
天扣丁小编给大家总结一下关于经常在a标签中看到href="javascript:void(0),但是并没有认真的研究过,正好看到了这篇文章,涨涨姿势。
请输入图片描述
由于JS表达式偏啰嗦,于是最近便开始采用Coffeescript来减轻负担。举个栗子,当我想取屋子里的第一条dog时,首先要判断house对象是否存在,然后再判断house.dogs是否存在,最后取house.dogs[0]。在JS需要这么写
vardog=(typeofhouse!=='undefined&&house!==null)&&house.dogs&&house.dogs[0]
在Coffee中,我只需要这么写:
dog=house?.dogs?[0];
写到这里,读者会问,这跟标题《Javascript中的void》有一毛钱关系?Coffee的本质就是JS,之所以Coffee能工作的很好,是因为它生成出了高效而且健壮的JS代码,我们可以看看它的生成结果。
vardog,_ref;
dog=typeofhouse!=="undefined"&&house!==null?(_ref=house.dogs)!=null?_ref[0]:void0:void0;
短短一行Coffee代码生成出了如此长的JS代码,看上去似乎比我最前面自己用JS写的更靠谱更安全,末尾还出来了两个void0,这究竟是何方神圣?
结构化一下上面的例子:
dog=(typeofhouse!=="undefined"&&house!==null)?
((_ref=house.dogs)!=null?_ref[0]:void0)
:void0;
如果house未定义或house为null时,返回void0
如果house.dogs为null时,返回void0
可void0究竟是什么值,这个倒很容易测试:
typeofvoid0//得到"undefined"
console.log(void0)//输出undefined
似乎void0就是undefined了,但这样子路数太野,也不够严谨,即无法回答:void100,voidhello(),voidi++这无数可能组合的值是什么?
我们来瞅瞅规范是怎么说的吧。
规范是这么说的
在ECMAScript262规范,有如下描述:
ThevoidOperator
TheproductionUnaryExpression:voidUnaryExpressionisevaluatedasfollows:
LetexprbetheresultofevaluatingUnaryExpression.
CallGetValue(expr).
Returnundefined.
NOTE:GetValuemustbecalledeventhoughitsvalueisnotusedbecauseitmayhaveobservableside-effects.
搬译一下:
void操作符
产生式UnaryExpression:voidUnaryExpression按如下流程解释:
令expr为解释执行UnaryExpression的结果。
调用GetValue(expr).
返回undefined.
注意:GetValue一定要调用,即使它的值不会被用到,但是这个表达式可能会有副作用(side-effects)。
重点在于:无论void后的表达式是什么,void操作符都会返回undefined.因此上面由Coffee编译出来的代码我们可以认为是这样的:
dog=(typeofhouse!=="undefined"&&house!==null)?
((_ref=house.dogs)!=null?_ref[0]:undefined)
:undefined;
问题来了,既然(void0)===undefined,那直接写undefined不就行了么?
为什么要用void?
因为undefined在javascript中不是保留字。换言之,你可以写出:
functionjoke(){
varundefined="helloworld";
console.log(undefined);//会输出"helloworld"
}
console.log(undefined);//输出undefined
对的,你可以在一个函数上下文内以undefined做为变量名,于是在这个上下文写的代码便只能通过从全局作用域来取到undefined,如:
window.undefined//浏览器环境
GLOBAL.undefined//Node环境
但要注意的是,即便window,GLOBAL仍然可以在函数上下文被定义,故从window/GLOBAL上取undefined并不是100%可靠的做法。如:
functionx(){
varundefined='helloworld',
f={},
window={
'undefined':'joke'
};
console.log(undefined);//helloworld
console.log(window.undefined);//joke
console.log(f.a===undefined);//false
console.log(f.a===void0);//true
}
于是,采用void方式获取undefined便成了通用准则。如underscore.js里的isUndefined便是这么写的:
_.isUndefined=function(obj){
returnobj===void0;
}
除了采用void能保证取到undefined值以外,还有其它方法吗?有的,还有一种方式是通过函数调用。如AngularJS的源码里就用这样的方式:
(function(window,document,undefined){
//.....
})(window,document);
通过不传参数,确保了undefined参数的值是一个undefined。
其它作用
除了取undefined外,void还有什么其它用处吗?
还有一个常见的功能,填充href。下面是一个微博截图,它的转发,收藏,讨论都是超链接,但是用户并不希望点击它们会跳转到另一个页面,而是引发出一些交互操作。
理论上而言,这三个超链接都是没有URL的,但如果不写的话,呵呵,点击它会刷新整个页面。于是便用上了href="javascript:void(0)的方式,确保点击它会执行一个纯粹无聊的void(0)。
另一种情况是,如果我们要生成一个空的src的image,最好的方式似乎也是src='javascript:void(0)',参见StackOverflow上的这个问题:What’sthevalidwaytoincludeanimagewithnosrc?
写在最后
回到void的定义,有一句话特别让人迷惑:
注意:GetValue一定要调用,即使它的值不会被用到,但是这个表达式可能会有副作用(side-effects)。
这是什么意思?这表示无论void右边的表达式是什么,都要对其求值。这么说可能不太明白,在知乎上有过阐述关于js中void,既然返回永远是undefined,那么GetValue有啥用?,我且拾人牙慧,代入一个场景,看代码:
varhappiness=10;
vargirl={
getwhenMarry(){
happiness--;
return1/0;//Infinity
},
gethappiness(){
returnhappiness;
}
};
console.log(girl.whenMarry);//调用了whenMarry的get方法
console.log(girl.happiness);//9
voidgirl.whenMarry;//调用了whenMarry的get方法
console.log(girl.happiness);//8
deletegirl.whenMarry;//没有调用whenMarry的get方法
console.log(girl.happiness);//还是8
上述代码定义了一个大龄文艺女青年,每被问到什么时候结婚呀(whenMarry),happiness都会减1。从执行情况可以看出,无论是普通访问girl.whenMarry,还是voidgirl.whenMarry都会使她的happiness--。而如果把void换成delete操作符写成deletegirl.whenMarry,她的happiness就不会减了,因为delete操作符不会对girl.whenMarry求值。
总结
void有如下作用:
通过采用void0取undefined比采用字面上的undefined更靠谱更安全,应该优先采用void0这种方式。
填充
(href和src中采用javascript:伪协议,导致浏览器会执行后面的代码,根据返回值来决定下一步操作,当返回值是undefined时浏览器不会把返回值替换页面里的内容,也就不会导致href和src的值发生改变)
*请认真填写需求信息,我们会在24小时内与您取得联系。