180306 表达式

表达式是js中的一个短语,js解释器会将其计算出一个结果。

原始(原始值)表达式

  • 常量
  • 直接量
 1.23          //数字直接量
'hello'        //字符串直接量
/pattern/     //正则表达式直接量  
  • 关键字
true   //返回一个布尔值:真
false  //返回一个布尔值:假
null   //返回一个值:空
this   //返回'当前'对象
  • 变量
a            //返回变量a的值
undefined    //undefined是全局变量,它不是一个关键字
  • 当js中出现了标识符,js会将其当作变量而去查找它的值。如果变量名不存在,表达式运算结果为undefined。而在es5严格模式中,对不存在的变量进行求值会抛出一个错误异常。

对象和数组的初始化表达式

对象和数组的初始化表达式实际上是一个新创建的对象和数组。这些初始化表达式有时称作 ‘对象直接量 ’,‘数组直接量 ’
和布尔值直接量不同,它们不是原始表达式,因为 它们所包含的成员或者元素都是子表达式。

  • 数组直接量中的列表逗号之间的元素可以省略,这时省略的空位会填充值undefined。
var s = [1,,,,5];
  • 对象直接量中的属性名可以是字符串而不是标识符。
var s = {'apple':{a:1,b:2}}

函数定义表达式

也可以叫做函数直接量

var square = function(x){return x * x};

属性访问表达式

属性访问表达式运算 得到一个对象属性或一个数组的值。

expression.identifer
expression[expression]   //如果属性名称是一个【1】保留字或者包含【2】空格和标点符号,或者是【3】数字(对于数组来说)则必须使用方括号。
var o = {x:1,y:{z:3}};
var a = {o,4,[5,6]};
o.x         // 1:表达式o的属性x
o.y.z       // 3:表达式o.y的z属性
o['x']      // 1:表达式o的属性x
a[1]        // 4:表达式a中索引为1的元素
a[2]['1']   // 6:表达式a[2]中索引为1的元素
a[0].x      // 1:表达式a[0]的x属性

调用表达式

是一种调用函数或方法的语法表示。函数表达式开始,表达式后跟随一个括号,括号内是一个以逗号隔开的参数列表。

f(0)  // f 是一个函数表达式,0是一个参数表达式
Math.max(x,y,z)  // Math.max 是一个函数;x,y,z是参数
a.sort()  // a.sort 是一个函数,它没有参数

如果函数使用return语句给出一个返回值,那么这个返回值就是整个调用表达式的值。

如果一个表达式是属性访问表达式,那么这个调用称做 ‘方法调用’。

在方法调用中,执行函数体的时候,作为属性访问主题的对象和数组便是其调用方法内this的指向。这种特性使得在面向对象编程范例中,函数可以调用其宿主对象。


对象创建表达式

创建一个对象并调用一个函数初始化新对象的属性。

调用的函数称作构造函数

对象创建表达式和函数调用表达式非常相似,只是对象创建表达式之前多了一个关键字new,如果对象创建表达式不需要传如任何参数给构造函数的话,那么括号可以省略

new Object()
new Point(2,3)
new Object
new Date

运算符概述

运算顺序

var a = 1;
var b =(a++)+a; //它这步a不变,这步结束a自增
console.log(b);

正确顺序:

  1. 计算b [b = (a++)+a]
  2. 计算a++ (设 c) [c = 1]
  3. 计算a [a = 2]
  4. 计算c+a [3]
  5. c+a结果赋值给b [3]

算数表达式

‘+’ 运算符

  • 加法或字符串连接。
  • 如果存在字符串或类字符串(对象转换为字符串),优先考虑字符串连接。
  • 加法操作符行为:
    如果其中一个操作数是对象,则根据对象到原始值的准换规则转换成原始值。【toString() valueOf()】
    转换后,如果其中一个操作数是字符串,另一个操作数也会被转换为字符串,然后进行连接。
    否则,都转换成数字加法操作。
1 + 2 // 3 : 加法
'1' + '2' // '12' : 字符串连接
'1' + 2  // '12' : 数字转换为字符串后进行字符串拼接
1 + {} // '1[object Object]':对象转换为字符串后进行字符串连接
true + true // 2 : 布尔值转化为数字后做加法
2 + null // 2 : null转化为0后做加法
2 + undefined // NaN : undefined转换为NaN后做加法

一元算数运算符
’ + ’ ’ - ’ ’ ++ ’ ’ – ‘

  • 根据需要把操作数转换为数字。

位运算符


关系表达式

相等和不相等运算符

比较运算符

  • 更偏爱数字,只有两个都是字符串的时候才会进行字符串的比较
11 < 3 // 数字比较,false
'11' < '3' // 字符串比较,true
'11' < 3  // 数字的比较,false
'one' < 3 //数字的比较,'one'转换为NaN,false

in运算符

  • in运算符希望它的左操作数是一个字符串或可以转换为字符串,希望它的右操作数是一个对象。
  • 如果右侧的对象 拥有一个名为左操作数值的属性名(索引),那么表达式返回true
var point = {x:1,y:1};
'x' in point   // true : 对象有一个名为'x'的属性
'z' in point   // false : 对象中不存在名为'z'的属性
'toString' in point    // true : 对象继承了toString()方法
var data = [7,8,9];   
'0' in data    // true : 数组包含元素'0'
1 in data      // true : 数字转换为字符串
3 in data      // false : 没有索引为3的元素

instanceof运算符

  • instanceof运算符希望左操作数是一个对象,右操作数标识对象的类。
  • 如果左侧的对象是右侧的实例,则返回true。
  • JS中对象的类是通过初始化它们的构造函数来定义的,这样右操作数是一个函数。
var d = new Date();
d instanceof Date  // true : d是由Date()创建的
d instanceof Object  // true : 所有的对象都是Object()的实例
d instanceof Number  // false : d不是一个Number对象
var a = [1,2,3];
a instanceof Array  // true : a是一个数组
a instanceof Object // true : 所有的数组都是对象
a instanceof RegExp // false : 数组不是正则表达式
  • 所有的对象都是Object的实例。当通过instanceof判断一个对象是否是一个类的实例的时候,这个判断也会包含对‘父类’的检测。

逻辑表达式

逻辑与(&&)

并不总是返回true和false。

运算符首先计算左操作数的值,即首先计算’&&’左侧的表达式。如果计算结果是假值,那么整个表达式的结果一定也是假值,因此’&&’这时简单地返回左操作数的值,而并不会对右操作数进行计算。

如果左操作数是真值,那么整个表达式的结果则依赖于右操作数的值。如果右操作数是真值,那么整个表达式也是真值。因此,当左操作数的真值时,’&&’运算符计算右操作数的值并将其返回作为整个表达式的计算结果。

var a = 10 && 20;   20


var o = {x:1};
var p = null;
o && o.x  // 1:o是真值,因此返回值为o.x
p && p.x  // null:p是假值,因此返回值为p
// 计算表达式p.x会抛出一个错误异常,而使用逻辑与运算符避免了问题。

逻辑与运算是否继续执行,看左操作数是否为真值或转换为真值
如果能,执行右操作数,返回右操作数的值;如果为假值或转换为假值,返回左操作数的值,不继续计算。

可以称这种特性为“短路”。

if (a == b) stop();
a == b && stop();

逻辑或(||)

首先计算第一个操作数的值,也就是说会首先计算左侧的表达式。如果计算结果为真值,那么返回这个真值。否则,再计算第二个操作数的值,并返回这个表达式的结果。

常用方式是用来从一组备选表达式中选出第一个真值表打式:

var a = 10 || 20;    10 遇到真就返回

//如果max_width已经定义了,直接使用它;否则再preferences对象中查找max_width
//如果没有定义它,则使用一个写死的常量
var max = max_width || preference.max_width || 500

或者用来给参数提供默认值:

// 将o的成员属性复制到p中,并返回p
function(o,p){
    p = p || {}; //如果向参数p没有传入任何对象,则使用一个新创建的对象
}

逻辑非(!)

首先将其操作数转换为布尔值,然后再对布尔值求反。也就是说’!’总是返回true或者false,并且可以通过使用两次逻辑非运算得到一个值的等价布尔值:!!x


赋值表达式

带操作的的赋值运算

  • 大多数情况下,表达式为:a op= b
    和下面的表达式等价:a = a op b

  • 注意:在第一行中,表达式计算了一次,第二行计算了两次。
    只有在a包含具有副作用的表达式(比如函数调用和赋值操作)的时候,两者才不等价。

  • a op= b + c -> a = a op (b + c)
var a = [10, 20, 30, 40];
var b = [10, 20, 30, 40];

var i = 0;   
var j = 0;

var test1 = a[i++] *= 2;
// a[0] = 10 * 2;
var test2 = b[j++] = b[j++] * 2;
// b[0] = b[1] * 2; 

i = 1; j = 2; test1 = 20; test2 = 40;
a = [20,20,30,40]; b = [40,20,30,40] 

表达式计算

eval()


其它运算符

  • 条件运算符
    条件运算符是JS中唯一一个三元运算符。
x > 0 ? x : -x  // 求绝对值

应用场景:判断一个变量是否有定义(并拥有一个有意义的真值)

greeting = 'hello' + (username ? username : 'there');
// 与下面等价,更简洁
greeting = 'hello';
if(username)
    greeting += username;
else
    greeting += 'there';
  • typeof运算符
x                typeof x
undefined       'undefined'
null            'object'
true false      'boolean'
数字,NaN        'number'
字符串           'string'
函数             'function'
内置对象          'object'
宿主对象          有编译器各自实现的字符串,但不是以上的返回值 

typeof最常用的用法是写在表达式中:

(typeof value == 'string') ? " ' " + value + " ' " : value

typeof可以带上括号,让其看起来像一个函数名:

typeof(i)

typeof对于区分原始值很有效,对于对象的类,则需要使用其他手段:instanceof运算符,class特性,constructor属性。数组会被返回为’object’。

  • delete运算符
var o = {x:1,y:2};
delete o.x;
'x' in o 

var a = [1,2,3];
delete a[2];
2 in a;   //false:元素2在数组中已经不存在了
a.length  //3:注意数组长度还是3,尽管删除了这个元素,但删除后留下了一个洞,没有修改数组长度。

注意:删除属性或者删除数组元素不仅仅是设置了一个undefined的值,这个属性将不再存在。读取一个不存在的属性将返回undefined,所以检测这个属性是否真正的消失可以通过in运算符。

  • void运算符

操作数正常计算,但忽略计算结果并返回undefined。由于void会忽略操作数的值,因此在操作数具有副作用的时候使用void来让程序更具语义。
这个运算符最常用在客户端的URL中—-JavaScript:URL中,在URL中可以写带有副作用的表达式,而void则让浏览器不必显示这个表达式的计算结果:

<a href="javascript: window.open();">打开一个窗口</a>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值