日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript面试时候的坑洼沟洄——表达式与运算符

發(fā)布時(shí)間:2024/4/14 javascript 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript面试时候的坑洼沟洄——表达式与运算符 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上篇博客JavaScript面試時(shí)候的坑洼溝洄——數(shù)據(jù)類型總結(jié)了一下JavaScript數(shù)據(jù)類型幾轉(zhuǎn)換的相關(guān)知識(shí),很多朋友可能和我一樣,買了書后對(duì)數(shù)據(jù)類型啊、運(yùn)算符啊、語句啊都是掃兩眼或直接略過的,自己為搞定原型、閉包、作用域鏈就可以秒殺JavaScript筆試題,結(jié)果一次次死在毫不起眼的基礎(chǔ)知識(shí)上,看似平淡無奇實(shí)則暗流涌動(dòng),一不小心就會(huì)栽倒。好了不扯淡了,回正題

神馬是表達(dá)式

表達(dá)式是由數(shù)字、運(yùn)算符、數(shù)字分組符號(hào)(如括號(hào))、自由變量和約束變量等以能求得數(shù)值的有意義排列方法所得的組合。~~約束變量在表達(dá)式中已被指定數(shù)值,而自由變量則可以在表達(dá)式之外另行指定數(shù)值。一個(gè)表達(dá)式代表一個(gè)函數(shù),其輸入為自由變量的定值,而其輸出則為表達(dá)式因之后所產(chǎn)生出的數(shù)值。 ——維基百科

看起來很不接地氣的趕腳,表達(dá)式是JavaScript中的一個(gè)短語,JavaScript會(huì)將其計(jì)算出一個(gè)結(jié)果,常量如1、"hello"、null這些都是表達(dá)式;變量名也是表達(dá)式,JavaScript計(jì)算出的結(jié)果就是賦值給變量的值,這些都是簡單的表達(dá)式,幾個(gè)簡單的表達(dá)式可以組合為復(fù)雜的表達(dá)式,[3,4,5,6]這也是一個(gè)表達(dá)式,計(jì)算結(jié)果是數(shù)組,我們也可以通過運(yùn)算符將簡單表達(dá)式組合位復(fù)雜表達(dá)式,8+9這樣,JavaScript表達(dá)式有幾種形式

  • 原始表達(dá)式

    常量、變量、保留字

  • 對(duì)象、數(shù)組初始化表達(dá)式

    var obj={a:1,b:2};
    var a=[1,2,3];

  • 函數(shù)定義表達(dá)式

    var fn=function(){}

  • 屬性訪問表達(dá)式

    Math.abs

  • 調(diào)用表達(dá)式

    alert('hello');

  • 對(duì)象創(chuàng)建表達(dá)式

    new object();

  • 函數(shù)定義

    我們想使用一個(gè)函數(shù)的時(shí)候通常有幾種做法

  • 函數(shù)表達(dá)式

    函數(shù)表達(dá)式中函數(shù)名稱并不是必需的,所以我們經(jīng)常這么使用
    var fn=function(n) { console.log(n) };

  • 函數(shù)聲明

    更常見的做法是這樣
    function fn(n){ console.log(n);}

  • 使用Function構(gòu)造函數(shù)

    偶爾也會(huì)這樣 var fn=new Function('n',"console.log(n);");

  • 這幾種做法都很好理解,但是如果函數(shù)表達(dá)式使用了名字呢,我們看個(gè)題目

    var f = function g(){ console.log(g);}; f();//function g(){ console.log(g);}; typeof g();//g is not defined

    不知道結(jié)果和同學(xué)們的預(yù)期是否一致,但看起來這種結(jié)果似乎互相矛盾,當(dāng)我們使用函數(shù)聲明的方式定義一個(gè)函數(shù)的時(shí)候,實(shí)際上聲明了一個(gè)變量,在上面例子中就是f,并把函數(shù)賦值給這個(gè)變量,普通的函數(shù)表達(dá)式?jīng)]有創(chuàng)建該變量,也就是我們所說的創(chuàng)建了一個(gè)匿名函數(shù),但是如果函數(shù)表達(dá)式包含名稱,也就是上面例子的g,那么函數(shù)的局部作用域?qū)瑢撁Q,并且把創(chuàng)建的函數(shù)綁定到該名稱上,在上面例子中g(shù)變成了函數(shù)的局部變量,變量指向函數(shù)本身,所以我們調(diào)用f的時(shí)候會(huì)把其本身打印出來。但是g只作為函數(shù)的局部變量存在,我們?cè)谕獠空{(diào)用g的時(shí)候就會(huì)報(bào)錯(cuò)了。

    命名函數(shù)表達(dá)式在創(chuàng)建的時(shí)候,會(huì)在當(dāng)前作用域最前段添加一個(gè)新的對(duì)象
    {func_name:refer_function_expression},然后,將作用域鏈添加到
    函數(shù)表達(dá)式的[[scope]]中,接著在刪除該對(duì)象。

    看個(gè)題目

    var x=1; if(function f(){}){x+=typeof f; } console.log(x);//'1undefined'

    是不是覺得自然就能想到答案了

    立即執(zhí)行函數(shù)

    初學(xué)JavaScript的同學(xué)很容易被類似這樣的東西唬住

    (function(){})();

    其實(shí)我們了解了表達(dá)式就能很清楚的看明白這是什么結(jié)構(gòu)了

    (函數(shù)定義表達(dá)式)函數(shù)調(diào)用表達(dá)式

    也就是說先創(chuàng)建了一個(gè)匿名函數(shù),然后不傳入?yún)?shù)調(diào)用它,這就變成了“立即執(zhí)行函數(shù)”,知道了這些看個(gè)傳入?yún)?shù)調(diào)用的立即執(zhí)行函數(shù)題目

    (function f(f){return typeof f();// "number" })(function(){return 1;});

    這個(gè)題目事實(shí)上還涉及了一些其它的知識(shí),立即執(zhí)行函數(shù)不再是以空括號(hào)()來調(diào)用了,同事傳入了一個(gè)function作為參數(shù)傳入調(diào)用。再一個(gè)疑惑就是typeof f() 中的f究竟指誰,這個(gè)知識(shí)我們后面會(huì)介紹道,簡單說一下,當(dāng)函數(shù)執(zhí)行有命名沖突的時(shí)候,函數(shù)依次填入 變量=》函數(shù)=》參數(shù),所以最后被填入的參數(shù)f會(huì)覆蓋函數(shù)定義f,typeof f()是對(duì)參數(shù)的調(diào)用,參數(shù)是立即執(zhí)行函數(shù)傳入的function參數(shù),返回?cái)?shù)字1,typeof 1是 "number"。

    表達(dá)式返回值

    表達(dá)式看明白了,我們卻經(jīng)常忽略其計(jì)算結(jié)果,也就是我們常說的返回值,對(duì)于原始表達(dá)式、對(duì)象數(shù)組初始化表達(dá)式、屬性訪問表達(dá)式很簡單不會(huì)有什么問題。

    函數(shù)定義表達(dá)式返回的是函數(shù)對(duì)象本身,我們?cè)谡{(diào)用alert或者console.log的時(shí)候會(huì)調(diào)用其toString方法

    console.log(function(){alert('a');}) //function (){alert('a');}

    函數(shù)調(diào)用表達(dá)式自然是返回函數(shù)的return結(jié)果,但在JavaScript中并不是所有的函數(shù)都有return語句,對(duì)于沒有return語句的function,其調(diào)用表達(dá)式返回undefined,對(duì)于只寫個(gè)return的坑爹做法同樣也是返回undefined

    (function(){})(); //undefined (function(){return;})();//undefined

    對(duì)象創(chuàng)建表達(dá)式本來也應(yīng)該很簡單,返回new的對(duì)象就可以了

    typeof new Date(); //"object"

    但是總有特殊的,看個(gè)題目

    function Test(){return new Date(); } var test=new Test(); console.log(test instanceof Test);//false console.log(test);//Sat Jan 18 2014 14:57:08 GMT+0800 (CST)

    很奇怪啊,new Test()沒有返回Test的實(shí)例對(duì)象,返回的卻是Date對(duì)象,這是為什么呢?是不是有返回值的function使用構(gòu)造函數(shù)的時(shí)候就會(huì)返回return指令的結(jié)果呢?看個(gè)例子

    function Test(){return new Date(); } function Test2(){return 2; } typeof new Test(); new Test2() instanceof Test2;//true,竟然是true

    剛才的推測(cè)明顯不正確,Test2有返回值,new test2() 返回的是Test2的實(shí)例,但是我們已經(jīng)可以看出一絲端倪了

    當(dāng)使用function的構(gòu)造函數(shù)創(chuàng)建對(duì)象(new XXX)的時(shí)候,如果函數(shù)return基本類型或者沒有return(其實(shí)就是return undefined)的時(shí)候, new 返回的是對(duì)象的實(shí)例;如果 函數(shù)return的是一個(gè)對(duì)象,那么new 將返回這個(gè)對(duì)象而不是函數(shù)實(shí)例。

    這里千萬別把構(gòu)造函數(shù)(使用new)和普通函數(shù)調(diào)用混淆了,普通函數(shù)調(diào)用還是該返回什么返回什么的。看個(gè)題目

    'foo' == new function(){ return String('foo'); }; //false 'foo' == new function(){ return new String('foo'); };//true

    怎么樣,答對(duì)沒有?

    正則表達(dá)式

    關(guān)于表達(dá)式還有一個(gè)重點(diǎn)沒有說——正則表達(dá)式,相關(guān)內(nèi)容已經(jīng)總結(jié)位單獨(dú)博客,有興趣同學(xué)可以看看

    JavaScript 正則表達(dá)式上——基本語法

    JavaScript正則表達(dá)式下——相關(guān)方法

    運(yùn)算符

    JavaScript中運(yùn)算符主要用于連接簡單表達(dá)式,組成一個(gè)復(fù)雜的表達(dá)式。常見的有算數(shù)表達(dá)式、比較表達(dá)式、邏輯表達(dá)式、賦值表達(dá)式等,也有單目運(yùn)算符,指操作原始表達(dá)式。大多數(shù)運(yùn)算符都由標(biāo)點(diǎn)符號(hào)組成(+、>=、!),也有關(guān)鍵字表示的運(yùn)算符,如typeof、delete、instanceof等。

    一些運(yùn)算符可以作用于任何數(shù)據(jù)類型(typeof),但大部分操作符“希望”操作數(shù)是特定的類型,而且大部分操作符會(huì)計(jì)算出(我們也常說返回)一個(gè)特定類型的值(typeof返回的全是string)。在JavaScript中運(yùn)算符通常會(huì)根據(jù)需要對(duì)操作數(shù)進(jìn)行類型轉(zhuǎn)換,乘法操作符 "" 希望操作數(shù)是數(shù)字,但是 "3""5"也是合法的,JavaScript會(huì)自動(dòng)將其轉(zhuǎn)換為數(shù)字計(jì)算,返回Number 15。

    有些操作符對(duì)不同的數(shù)據(jù)類型有不同的含義,比如 "+"

    console.log(2+4);//6 console.log("2"+"4");//"24" console.log(2+"4");//"24" console.log(2+new Date());//"2Mon Jan 20 2014 17:15:01 GMT+0800 (China Standard Time)" console.log(+"4");//4
    • 在兩個(gè)操作數(shù)都是數(shù)字的時(shí)候,會(huì)做加法運(yùn)算
    • 兩個(gè)參數(shù)都是字符串或在有一個(gè)參數(shù)是字符串的情況下會(huì)把另外一個(gè)參數(shù)轉(zhuǎn)換為字符串做字符串拼接
    • 在參數(shù)有對(duì)象的情況下會(huì)調(diào)用其valueOf或toString
    • 在只有一個(gè)字符串參數(shù)的時(shí)候會(huì)嘗試將其轉(zhuǎn)換為數(shù)字
    • 在只有一個(gè)數(shù)字參數(shù)的時(shí)候返回其正數(shù)值

    運(yùn)算符優(yōu)先級(jí)與結(jié)合性

    優(yōu)先級(jí)什么意思大家都清楚,結(jié)合性是指多個(gè)具有同樣優(yōu)先級(jí)的運(yùn)算符表達(dá)式中的運(yùn)算順序。有的運(yùn)算符是左結(jié)合的,即運(yùn)算從左到右執(zhí)行,下面兩個(gè)運(yùn)算是一樣的

    w=x+y+z; w=(x+y)+z;

    有的運(yùn)算符是右結(jié)合的

    w=x=y=z; w=(x=(y=z)); w=a:b:c?d:e?f:g; w=a?b:(c?d:(e?f:g));

    運(yùn)算符的優(yōu)先級(jí)《JavaScript權(quán)威指南》中有個(gè)表闡述的很好(我去掉了位運(yùn)算部分),其中R/L代表結(jié)合性是右結(jié)合還是左結(jié)合,num->num表示操作符期望的數(shù)據(jù)類型和計(jì)算結(jié)果類型,lval指左值

    運(yùn)算符操作結(jié)合性類型
    ++自增Rlval->num
    --自減Rlval->num
    -求反Rnum->num
    +(一個(gè)操作數(shù))轉(zhuǎn)換為數(shù)字Rnum->num
    ~按位求反Rint->int
    !邏輯非Rbool->bool
    delete刪除屬性Rlval->bool
    typeof檢測(cè)數(shù)據(jù)類型Rany->str
    void返回undefinedRany->undefined

    *、/、%乘、除、求余Lnum,num->num

    +、-加、減Lnum,num->num
    +字符串拼接Lstr,str->str
    、>=數(shù)字大小或字母表順序Lnum/str,num/str->bool
    instanceof對(duì)象類型Lobj,function->bool
    in測(cè)試屬性是否存在Lstr,obj->bool

    ==判斷相等Lany,any->bool
    !=判斷不等Lany,any->bool
    ===判斷恒等Lany,any->bool
    !==判斷非恒等Lany,any->bool

    &&邏輯與Lany,any->any
    ||邏輯或Lany,any->any
    ?:條件運(yùn)算符Rbool,any,any->any
    =賦值 *=、/=、+=、-= 賦值 運(yùn)算且賦值Rlval,any->any
    ,忽略第一個(gè)操作數(shù),返回第二個(gè)操作數(shù)Lany,any->any

    有幾個(gè)我們需要注意的地方

    • typeof的優(yōu)先級(jí)相當(dāng)?shù)母?#xff0c;比加減乘除神馬的都高,所以雖然是操作符,在在復(fù)雜表達(dá)式的時(shí)候我們還是習(xí)慣家括號(hào),看個(gè)例子
    typeof 2*3;//NaN typeof (2*3);//"number" typeof 2+3;// "number3"
    • ++、--是右結(jié)合的操作符(優(yōu)先級(jí)最高的幾個(gè)都是右結(jié)合),而且比加減乘除優(yōu)先級(jí)高。同時(shí)自增、自減運(yùn)算符的運(yùn)算數(shù)得是左值(可以放在賦值符號(hào)左邊的值),而不能是常數(shù)
    4++; //ReferenceError: Invalid left-hand side expression in postfix operation var a=0,b=0; a+++b;//0 a;//1,++優(yōu)先級(jí)比+高,所以相當(dāng)于(a++)+b b;//0
    • 賦值運(yùn)算符的優(yōu)先級(jí)相當(dāng)?shù)牡?/li>
    a=b==c;//等同于a=(b==c)
    • 邏輯非!也在優(yōu)先級(jí)隊(duì)列的前端,比加減乘除高,但邏輯與、邏輯或優(yōu)先級(jí)很低,不如加減乘除
    !2*0; //0, 等價(jià)于(!2)*0
    • 一個(gè)關(guān)于邏輯運(yùn)算符的有意思地方是其“短路”功能,相信大家都有所了解,但有些題目不那么單純,會(huì)結(jié)合表達(dá)式計(jì)算值來考察
    1 && 3; 1 && "foo" || 0; 1 || "foo" && 0

    了解了邏輯運(yùn)算符的“短路”特點(diǎn),在知道原始表達(dá)式的“返回值”就是本身,題目就很簡單了

    運(yùn)算順序

    我們?cè)谶\(yùn)算符的優(yōu)先級(jí)和“返回值”上關(guān)注了很多,一個(gè)經(jīng)常被我們忽略的知識(shí)點(diǎn)就是運(yùn)算順序問題,復(fù)雜的表達(dá)式是由運(yùn)算符和子表達(dá)式組成,優(yōu)先級(jí)和結(jié)合性決定了表達(dá)式的運(yùn)算順序,但是卻沒有規(guī)定子表達(dá)式的運(yùn)算順序,在JavaScript中嚴(yán)格按照從左到右的順序計(jì)算表達(dá)式,然后再按照優(yōu)先級(jí)和結(jié)合性計(jì)算各個(gè)表達(dá)式和運(yùn)算符作用結(jié)果。說的比較晦澀,看個(gè)例子

    var a=1; b=(a=3)+a++;

    這個(gè)例子中運(yùn)算順序是這樣的

  • 計(jì)算b
  • a=3
  • a++(設(shè)為c)
  • 計(jì)算a(這時(shí)候a變成了4已經(jīng),不是再最后才變得,但表達(dá)式使用的是a++的結(jié)果c,也就是a原來的值)
  • 計(jì)算3+c
  • 把3+c賦值給b
  • 相等

    我們知道可以使用"=="或"==="判斷兩個(gè)值的相等性,其中區(qū)別相信大家清楚,"==="是嚴(yán)格意義的相等,只需注意NaN和NaN不等就行了。而使用"=="的時(shí)候,javascript會(huì)幫我們做類型轉(zhuǎn)換,造成一些匪夷所思的結(jié)果,那么使用"=="的時(shí)候會(huì)在哪些情況下做類型轉(zhuǎn)換,又會(huì)換成什么樣子?

  • 如果兩個(gè)值類型相同,則執(zhí)行嚴(yán)格相等的運(yùn)算
  • 如果兩個(gè)值的類型不同
    ******
    • 如果一個(gè)是null,一個(gè)是undefined,那么相等
    • 如果一個(gè)是數(shù)字,一個(gè)是字符串,先將字符串轉(zhuǎn)為數(shù)字,然后比較
    • 如果一個(gè)值是true/false則將其轉(zhuǎn)為1/0比較
    • 如果一個(gè)值是對(duì)象,一個(gè)是數(shù)字或字符串,則嘗試使用valueOf和toString轉(zhuǎn)換后比較
    • 其它就不相等了
    null==undefined; NaN==NaN "1"==true

    轉(zhuǎn)載于:https://www.cnblogs.com/dolphinX/p/3524977.html

    超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

    總結(jié)

    以上是生活随笔為你收集整理的JavaScript面试时候的坑洼沟洄——表达式与运算符的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。