Go to comments

JavaScript 面试题04

001. EXAMINATION QUESTIONS

下面这段js代码执行完毕后 x,y,z 的值分别是多少?(百度14年的题)

var x = 1,
    y = z = 0;

function add(n){
    return n = n + 1;
}

y = add(x);

function add(n){
    return n = n + 3;
}

z = add(x);

console.log(x, y, z); // 1 4 4



/*
x,y,z初始值
var x = 1;
var y = 0;
    z = 0;

y = add(x); // y = 4

z = add(x); // z = 4

执行结果
    x = 1
    y = 4
    z = 4
*/

考的是预编译,预编译函数要提升,函数提升符合第4步规则。

第4步先去找函数的名,把函数声明的名变成AO的一个属性名,属性名的值是函数体。

有两个函数起了一样的名,后面的函数肯定覆盖第一函数。

别管函数定义的位置在哪,后面的函数会被提升提,提升后位置就无关紧要了。

所以最后无论是"y = add(x)"还是"z = add(x)",调用"add()"的函数都是一个,就是下面的那个函数。

002. EXAMINATION QUESTIONS

阿里巴巴的题,下面代码中console.log的结果是[1, 2, 3, 4, 5]的是:

A 选中

function foo(x){
    console.log(arguments);
    return x;
}

foo(1,2,3,4,5);


// foo(1,2,3,4,5)函数执行,1,2,3,4,5传到里面arguments是实参,打印实参是1,2,3,4,5的数组
// Arguments(5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]

function foo(x){
    console.log(arguments);
    return x;
}(1,2,3,4,5);


/***
B跟A一样,只不过函数后面直接加了一个小括号(1,2,3,4,5),想执行这个函数声明。能执行吗?执行不了,但不报错。

为什么不报错?

本质上,如果把小括号写到函数声明后面,它是一定会执行这个函数的,但是又执行不了,所以肯定会报错的。

但是把小括号写到后面,括号里面又写了点东西。其实系统最想识别的语法,还是执行这个函数,但执行这个函数又执行不了。

执行不了就会先默认,看看有没有其它的出口,不发生错误呢(发生错误就终止程序)?

能不能不发生错误呢?

"(1,2,3,4,5)",括号还可以把这些数圈到一起。

把这些数圈到一起,就相当于给这些数字,加一个数学运算的符号了,就不当做函数执行了,所以这样就不会报错。

function foo(x){
    console.log(arguments);
    return x;
}

(1,2,3,4)

这个题报不报错都无所谓,因为问是那个结果能输出,但这道题它怎么也输出不了!
***/

C 选中

(function foo(x){
    console.log(arguments);
    return x;
})(1,2,3,4,5);


// 立即执行函数里面传1,2,3,4,5,立即执行函数放小括号里面能执行。传进去之后,arguments还是1,2,3,4,5

D 选中

function foo(){
    bar.apply(null ,arguments);
}

function bar(){
    console.log(arguments);
}

foo(1,2,3,4,5);



/***
call和apply的区别传参列表不一样,作用改变this指向。

function foo(){

    // bar.apply(null ,arguments)就是让bar()去执行,apple()是改变this指向,但这里面不涉及this的事,所以第一位传的是null了,不想改变谁的this就是想执行,后面传的是arguments。
    // 这块写的bar.apply(null ,arguments)和bar(arguments)没什么两样!只不过秀一下!
    bar.apply(null ,arguments);
}
function bar(){
    console.log(arguments);
}
foo(1,2,3,4,5);

看一下最后输出结果,bar里面的arguments输出的是什么?打印Arguments(5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]

这个题做了一个参数的传导,怎么参数的传导呢?

首先foo()虽然它没写形参,没写形参不代表参数传不进去,实参列表里传着实参呢,foo里面的"arguments"(bar.apply(null ,arguments))代表实参列表1,2,3,4,5,这是foo自己的arguments。

然后foo()把arguments当做参数,又传到了bar()里面去,所以bar()里面有一个实参,是一个数组。

然后这个数组,又放到了bar()的arguments里面去了。就相当于把1,2,3,4,5打包又传到bar()的arguments里面去了,所以bar()的arguments存的还是1,2,3,4,5

倒了一下参数
***/

003.

PS:每语句结束基本上都加分号,作为这个语句的结束符号。有些语句是不用加分号的比如if(){}, for(){}, function(){}

我是一行文本需要水平垂直居中。

004. EXAMINATION QUESTIONS

我是一行文本,需要水平和垂直居中

<style>
div{
    width:400px;
    height:100px;
    border:1px solid gray;
    line-height:100px;
    text-align:center;
    position:absolute;
    top:50%;
    left:50%;
    margin-left:-200px;
    margin-top:-50px;
}
</style>

<div>我是一行文本,需要水平和垂直居中</div>

005. EXAMINATION QUESTIONS

请问以下表达式的结果是什么?

这题考的是parseInt()的应用,parseInt()前边的参数是要转化的数,后面是基底。基底是控制进制的,以后边的目标进制为基底转化为十进制

console.log(parseInt(3 ,8)); // 3当成八进制的3,八进制的3转化为十进制还是3

console.log(parseInt(3 ,2)); // 二进制里没有3,结果返回NaN

console.log(parseInt(3 ,0)); // 这个比较特殊,下面详解一下


/***
parseInt(3 ,0)

parseInt()后面的"基底"正常区间是2-36,有一个不正常的就是0。

写0,有些浏览器认为它是错的,因为根本不可能有零进制,一进制都不可能有,一进制就全是0了,一进制不能有1,二进制不能有2。一进制不可能有,0进制根本就不可能有。

有些浏览器(比如IE老版本)这么写"parseInt(3 ,0)"会报错,有的也不会报错是NaN。

现在高级谷歌浏览器,写0进制还真能识别,把写0进制写上,它认为没写,把0认为成10了,就跟没写一样,所以写3返回的还是3。

所以这个答案有两个,"other"也行"3、NaN、NaN"也行。
***/

006. 进制

大家都有一个查数的标准,正常人的查数标准是1,2,3,4,5,6,7,8,9然后是10,1到9以是个位数,在9的基础上再加1就变成10个了。

"10个"和10是一个东西吗?给你10个苹果,再写出一个10,这俩个不是一个东西,十个苹果就是10个苹果,这个10代表的只是十进制里面的计数10。

比如10个苹果想表示它10个的数量,按照十进制的数量表示那就是"一零"(10),因为9 + 1在十进制里面就等于"一零"(10),这是我们正常生活中用的。


但是比如我们的进制是十一进制的,那9 + 1也等于10,但在十一进制里面这个10还算是个位的, 所以为了在个位表示这个10就变成a了(9 + 1 = a),这时候a代表10,a再加1"a + 1 = 10",在十一进制里10代表11

十一进制和十进制的区别,十一进制满11就要向前进一位,所以"a + 1 = 10",在十一进制里的"一零"(10)代表11。


通用的没有那么复杂,一般十进制、十六进制、二十进制

十六进制就9上面在加,十六进制里面的10是a,11是b,然后c、d、e、f,这个f代表15

什么叫进制?满足一个数,它要从个位变成十位,这就叫进制。

十进制,满十就要让个位变成0,让十位变成1。

十六进制,满16让个位变成0,十位变成1,所以f在往上就是一零(10)了。

十六进制的一零(10),这个10可不是10,这叫十六进制的"一零","一零"代表的真实的数是16个。

比如给一个十六进制的数,"一零"(10)个苹果,十六进制的10其实是16个苹果。

再比如给f个苹果,是15个苹果。

"1f"个苹果是31个,怎么算31个的呢?回归十进制,19个苹果就是19个,19个是怎么来的?是10加上9(10 + 9),十位加个位。

十六进制的"1f"个苹果,也是十分位加上个分位的东西,十分位的"1"代表16,个位的"f"代表15,所以就是16 + 15 = 31


经典的是二进制,二进制最加的迷幻,满2就可以往前进位了。

所以二进制的1就是1,二进制里没有2,到2就往前进位了,二进制里的"一零"(10)代表2,二进制的11代表3。

二进制的"100"?4

二进制的"1000"?8

二进制的"10000"?

看一个简单的规律,不管几进制,先看十进制的规律。

十进制的1                                 1 = 1

十进制的10                               10 = 10

十进制的100是10的平方           100 = 10 ^ 2

十进制的1000是10的3次方       1000 = 10 ^ 3 

十进制的10000是10的4次方     10000 = 10 ^ 4

所以十进制的几?有几个零就是多少次方。十进制的"100"有两个0就是10的2次方,十进制"1000"有三个0就是10的3次方,就看有几个0。

二进制和十进制的规律类似。

二进制的1          1 = 1

二进制的10        10 = 2

二进制的100      100 = 2 ^ 2

二进制的1000    1000 = 2 ^ 3

二进制的10000  10000 = 2 ^ 4

007. EXAMINATION QUESTIONS

typeof返回的六个结果: String、Boolen、Number、undefined、Object、function 

那些是typeof返回的结果,那些值可以转换为false,这些是基础。

008. EXAMINATION QUESTIONS

javasctip的call和apply方法是做什么的,两种有什么区别? 改变this指向,区别传参列表不一样。

009. EXAMINATION QUESTIONS

看看下面console.log(a)的结果是什么?

function b(x ,y ,a){
    arguments[2] = 10;
    console.log(a);
}

b(1,2,3); // 10

/***
"arguments[2]"代表实参第二位,实参第二位就是形参第三个,也就是"a"。

"arguments[2]"和"a"有关系吗?有关系,它俩是相互映射的关系。

实参列表里面,实参的那个位和行参有值的那个位,是相互映射的。它俩虽然不是一个人,但是它俩保持一个关系,你动我就动,你改完也改。

现在"arguments[2] = 10",a也是变成10了,别看一开始a传的是3,但是会变成10的。

反过来,如果a变成10,打印arguments[2]呢?也是一样的变成10了。
***/

如果函数体改成下面,结果又会是什么?

function b(x ,y ,a){
    // var a; 形参隐式的声明变量a,所以a=10是局部变量    
    a = 10;
    console.log(arguments[2]);
}

b(1,2,3); // 10

010. EXAMINATION QUESTIONS

先铺垫一个基础"逗号操作符",逗号操作符干什么的呢?

比如在控制台1, 2回车,先看一眼前面的,然后在看一眼后面的,最后把第二个返回回来,也就是说1, 2的结果是2。

image.png

现在变量num等于1 ,2,num结果应该等于几?结果报错

var num = 1, 2; // Uncaught SyntaxError: Unexpected number

为什么会报错,因为不写括号是不行的。

var num = (1, 2);

console.log(num); // 2

要写一个等式就必须把这个东西给括起来,想要逗号操作符必须把这东西括起来。

否则会认为变量声明num等于1、逗号2什么什么东西了,相当于变量声明后一个逗号,相当于那个逗号,会识别混乱。

image.png

想要识别语法意义,一定要注意放到一起会不会发生语法混乱。所以想要逗号操作符实现操作加括号。

console.log((1, 2)); // 2

写出下面程序的执行结果(typeof的类型是什么):

var f = (
    function f(){
        return "1";
    },
    function g(){
        return 2;
    }
)();

typeof(f); // Number


/***
逗号操作符和这个题是一样的,变量f等于一个括号,括号里面一个逗号隔开两个函数,最后会把第二个函数function g(){}返回

返回后会变成这样,是一个立即执行函数,立即执行函数执行完要返回的是2,变量f变成数字2,"typeof f"返回Number

var f = (
    function g(){
        return 2;
    }
)();

typeof(f); //Number
***/

011. EXAMINATION QUESTIONS

写出下面程序的执行结果(这是一个很经典的题)

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


/***
这个题首先它很不符合语法规定,但是它就这么出了。

1. if括号里写了一个"function f(){}",括号还有什么什么东西,但凡把function变成了表达式的,function都会自动忽略它的引用"f"。

就是说一旦function变成了表达式,它就可以立即被执行了,但是相应的代价是它在也不可能被人找到了,这个名字"f"没有任何用了。

2. 虽然if括号里面写"function f(){}"挺匪夷所思的,但是确能写到里面去。能写到里面去,if这个括号表面上是作为条件判断的括号把"function f(){}"给括起来,实际上括号还有自己的用途,就是能把里面的东西转换成表达式。

3. 能转换成表达式,不论怎么转这个"function f(){}"肯定不是那六个能转化成false的值,所以结果一定是true,可用走到判断里面去。可以通过if判断,执行里面的"x+=typeof f"语句。

4. "x+=typeof f"这时候函数名"f"找不到了,因为函数放在括号里面,函数名f找不到了,找不到就是undefined,undefined正常情况下就报错了,但是唯独放到typeof里面没事,它能返回字符串格式的"undefined"

5. 所以数字1,数字1加上字符串"undefined",等于字符串"1undefined"
***/

012. EXAMINATION QUESTIONS

以下哪些表达式的结果为true

A. 

undefined == null


/***
undefined和null这俩非常有意思:
undefined  > 0  false   undefined不大于0
undefined  < 0  false   不小0
undefined == 0  false   不等于0
全是false

无论大、小、等于全是false和它类似的值还有null,null也不大0、null不小于0、null不等于0
null  > 0  false   null不大于0
null  < 0  false   不小0
null == 0  false   不等于0

undefined和null挺像所以它俩相等吧!
undefined == null  返回true它俩是相等的。

但它俩绝对等于吗,不绝对等于。
undefined === null  false
***/

B. 

undefined === null


/***
但它俩绝对等于吗,不绝对等于。
console.log(undefined === null); // false
***/

C.

isNaN("100");


/***
isNaN("100")结果不是NaN,所以返回true
isNaN()意思是否是NaN,标准的意思是,这个数经过Number()转化之后是不是NaN
isNaN("abc")这次返回true,它会先把"abc"放到Number里面经历隐式类型转换,然后再和NaN进行比对。
***/

D.

parseInt("1a") == 1;


// parseInt("1a")得出数字类型1,数字类型1肯定等于1返回true

按照C. 有一个探索能力,自己写一个isNaN()方法

function myIsNaN(num){
    var ret = Number(num); // 1. 调用Number(num)结果赋给ret,NaN自己都不等于自己,ret怎么比对呢?
    ret += "";             // 3. 把NaN转化成字符串的"NaN",然后在比对,是不是就等于"NaN"字符串了
    if(ret == "NaN"){      // 2. 一旦ret等于"NaN"就返回true,逻辑是这逻辑。NaN怎么和NaN比对?
        return true;
    }else{
        return false;
    }
}
console.log(isNaN('123')); // false
console.log(isNaN('abc')); // true
console.log(isNaN('NaN')); // true
console.log(isNaN(NaN));   // 放什么形式的NaN都返回true,这就和系统的一样了。

013. EXAMINATION QUESTIONS

问一个问题,空对象等于空对象吗?

123 == 123 //true

{} == {};     // false


/***
"{} == {}"不相等返回false,对象和对象比对的是什么呢?

原始值和原始值比对,只能是比对值了。一个对象代表一个房间,这是两房间,虽然外表长的一样但没有用,因为是引用值。这个房间和那个房间看起来格局一样,但毕竟是两个房间,所以肯定不等。

记住,引用值它比的是地址,地址一样才相等。
***/

这样写,两个对象指向一个房间,它俩必须相等,它俩也绝对相等,都是一个房间,干嘛不绝对相等!引用值比的是地址。

var obj = {};
var obj1 = obj;

console.log(obj1 == obj);  //true
console.log(obj1 === obj); //true

014. EXAMINATION QUESTIONS

请阅读以下代码,写出以下程序的执行结果:

var foo = '123';
function print(){
    var foo = '456';
    this.foo = '789';
    console.log(foo);
}
print(); // 456

请阅读以下代码,写出以下程序的执行结果:

function print () {
    console.log(foo);
    var foo = 2;
    console.log(foo);
    console.log(hello);
}

print();


Leave a comment 0 Comments.

Leave a Reply

换一张