关于类似(i++)+(++i)

  这是一个“然并卵”的问题,因为没有人愿意在代码中给自己找这种麻烦,看到书上讲到这个问题忍不住想顺势总结下,就从表达式说起吧。

  在js中,同一般的语言一样,表达式分很多种。

  • 对象和数组的初始化表达式:即声明一个对象或数组(有时也可看成对象)值,如
    var arr1 = [];                 //空数组
    var arr2 = [1,2,3+5];
    var arr3 = [1,,3,,6];
    var obj1 = {};               //空对象
    var obj2 = {x:3, y:5};

  逗号之间可以空着不写,js默认将其定义为undefined,而对象的属性在有空格时需要加引号以构成字符串的属性名,属性值可以是任意类型。嵌套定义也可以。通过这个中直接声明而来的,一般将其称为原始值或直接量,因为它们与真正通过new关键字得到的对象数组有一点差别。

  • 函数定义表达式:即将函数定义赋给一个变量,函数通过变量来调用,如
    var vl = function(){ document.write("function to a var.<br/>"); };
    vl();
  • 属性访问表达式:主要是obj[index]跟obj.prop两种形式,前者一般用于数组,后者一般用于对象,如
    var arr = [1,2,3];
    document.write(arr[0]+"<br/>");
    var obj = {x:1, y:5};
    document.write(obj.x+" "+obj["y"]);
  • 调用表达式:对普通函数的调用统称为函数调用,如果调用的是一个对象的方法,则可称为方法调用,如
   function  fun(){
       ;
   }
    fun();   //函数调用
    function Game(name){  //构造函数
        this.name = name;
        this.fly = function(){;}
    }
    var flappy_bird = new Game("flappy_bird");
    flappy_bird.fly();  //方法调用

  类似于对对象属性的引用,方法调用也会先计算点号左边是否是一个对象,不是对象的话将会抛出类型错误。

  • 对象创建:跟其他高级语言有点像,如
    var arr = new Array(1,2,3);
    var o = new Object;
    var date = new Date();

  还有跟运算符相关的算术表达式、关系表达式、逻辑表达式等、赋值表达式等,值得注意的是js的逻辑表达式并不一定返回布尔类型的true和false,如

    var ret1 = 5 && [1,2,3];
    document.write("ret1: type=>"+typeof(ret1)+" val:"+ret1+"<br/>");
    var ret2 = 0 || 5;
    document.write("ret2: type=>"+typeof(ret2)+" val:"+ret2+"<br/>");

  输出  

  但是在其他语言,比如php中,逻辑表达式的最终结果一定是布尔型的,这点需要区别。

  我们更容易忘记的是最简单的情形:原始表达式。所谓原始表达式是表达式的最小单位,它不在包含其他表达式,它就是最简单的常量、变量、原始值或关键字,如

    //原始值
    15;
    "hello";
    /[A-Z]\d+/;

    //关键字
    null;
    false;

    //变量
    index;
    sum;

  跟运算符扯上关系的,肯定要考虑运算符的优先级、结合性,优先级高的先运算,优先级高的先运算,还要看看是从左到右还是从右到左,比如经常用的连续赋值

    var a = b = c = 1;

  因为赋值运算符的结合性是从右到左,所以上面又等价于下面这样的:

    var a = (b = (c = 0));

  最后一点是运算符的运算顺序,通常我们只需要考虑优先级与结合性就够了,谈到运算顺序,它涉及的的是子表达式(父子关系总是相对的),如下面一段计算式

   w = x + y * z

  子表达式就是w、x、y、z,因为是最简单的变量,所以它们是原始表达式,js是按照从左到右的顺序来计算子表达式的,这里先依次计算w、x、y、z的子表达式的值,然后根据优先级和结合性,先计算y+z的值,再与x相加,将结果赋值给表达式w所指代的某个变量。

而我们一般碰到的情况是,计算x子表达式的时候,对y不会产生什么影响,一旦产生了影响(使用特殊运算符),如改变了y子表达式的值,这称为运算符的副作用(side effect)。能改变子表达式的值,肯定要对它赋值,所以一般具有赋值作用的运算符容易产生副作用,严格的说等号具有副作用,当然一般用等号肯定就是要改变等号左边表达式的值,谈个毛线副作用。

  回到(i++)+(++i),使用具有隐式赋值作用的自增运算符,自减自然也算,就产生副作用了,前面的先各一个i子表达式的初始值,假设i初始值为1,然后计算i++时,由于自增原因,自增计算过程中对 i 进行了赋值运算,i++这个整体表达式的值仍为1,再计算++i 时,i 这个子表达式的值已经是2(前面的赋值改变了它的大小),所以后面 i++的值是3,总的结果就是4。其他的,c/c++等的理解方式几乎相同。

  放佛又回到曾今被老师坑惨的c语言考试题=_=

时间: 2024-08-25 05:44:18

关于类似(i++)+(++i)的相关文章

用java写一个远程视频监控系统,实时监控(类似直播)我想用RPT协议,不知道怎么把RPT协议集成到项目中

我最近在用java写一个远程视频监控系统,实时监控(类似直播)我想用RPT协议,不知道怎么把RPT协议集成到项目中,第一次写项目,写过这类项目的多多提意见,哪方面的意见都行,有代码或者demo的求赏给我,谢谢

用python实现计算1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))类似的公式计算

作业需求: 开发一个简单的python计算器 1.实现加减乘除及拓号优先级解析 2.用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致 上图是实现的逻辑思路图,下面是对上图的分析: 整体的思想就是先匹配最

C#中“走马灯”和类似“打地鼠”的小程序

今天主要复习了一下昨天学习的窗体小程序.主要会运用到控件的一些基本属性. 程序: 走马灯(要求是:使用两个窗体,两个窗体之间要传值,Form1传值给Form2,传入的字符串在Form2窗体上横向滚动) * 首先是设定界面(txtname,txtpwd.第二个文本框txtname设置它的UseSystemPasswordChar属性为true,MaxLength设为6) 文本框的属性:UseSystemPasswordChar 指示编辑控件中的文本是否以默认的密码字符(“●”)显示.   Pass

所有橘子都有蛆虫,类似埃博拉病毒,大家最近不要买橘子,紧急通知!!

所有橘子都有蛆虫,类似埃博拉病毒,大家最近不要买橘子,紧急通知!!

istringstream字符串流,实现类似字符串截取的功能,字符串流中的put,str()将流转换成为字符串string

 1. istringstream字符串流 #include <iostream> #include <sstream> #include <string> using namespace std; struct MyStruct { string str1, str2, str3; double db; int num; char ch; }; void main() { string  mystring("china  google microsoft

实现类似shared_ptr的引用计数

13.27 定义使用引用计数版本的HasPtr #include<iostream> #include<string> #include<new> using namespace std; class HasPtr { public: HasPtr(const string &s=string()):ps(new string(s)),i(0),use(new size_t(1)) {cout<<"constructer"<

NetBeans自定义代码折叠块,类似vs中的#region

//<editor-fold defaultstate="collapsed" desc="测试代码折叠"> echo '<script type="text/javascript">'; echo "alert('当前类目下有文章,不能删除!');"; echo "history.go(-1)"; echo "</script>"; exit;//&

java合并两段音频成一段 同时播放类似伴奏

/** * * @param partsPaths 要合成的音频路径数组 * @param unitedFilePath 输入合并结果数组 */ public void uniteWavFile(String[] partsPaths, String unitedFilePath) { byte byte1[] = getByte(partsPaths[0]); byte byte2[] = getByte(partsPaths[1]); byte[] out = new byte[byte1.

解决类似 Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit)的问题

源码编译升级安装了gcc后,编译程序或运行其它程序时,有时会出现类似/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found的问题.这是因为升级gcc时,生成的动态库没有替换老版本gcc的动态库导致的,将gcc最新版本的动态库替换系统中老版本的动态库即可解决. 1. 问题原因分析 为了安装最新版本的Node.js(最新版本的Node.js使用了C++ 11中,而C++ 11需要code>gcc 4.8+才能支持),将gcc升级到了

如何用Elasticsearch实现类似SQL中的IN查询实例

我想实现类似如下sql语句的效果: select * from table1 where rw_id in ('7a482589-e52e-0887-4dd5-5821aab77eea','c68ace46-1c07-fccf-1cb6-57d4e77e40a2','3c9263d2-c44b-a9fd-155e-57aaf783ed58','69b087df-eb62-3e70-2cc0-582ec84a561b') 相应的ES查询应该写为: $v 即为 rw_id的集合,GET /_sear