奇葩面试题记录
1. var a = {n:100};
var b=a; 为什么要有这步, 因为后面对a的赋值操作会丢失a对{ n:100 } 的引用
a.x = a = { n:200 }; 这是核心考点
console.log( a.x );
console.log( b.x );
解析:
1). js的赋值运算顺序永远都是从右往左的,但是 a.x = a = { n:200 }中, 由于"."是优先级高于"="赋值运算符,所以这行代码先执行了a.x, 即 为变量a引用的{n:100}对象中添加x属性, 并初始化为undefined, 此时初始化完成, 就等待赋值了 此时 a 引用的对象变成了 { n:100, x: undefined }。
2). 这时才开始赋值操作, a = { n:200 } 再 a.x = { n:200 }, 这时不会因为a.x 中的a的引用变了, a.x再去重新初始化, 而是接着赋值给原先的a.x,即 { n:100, x:{ n:200 }}
总结: 最重要考点: 就是连等赋值 和 变量.属性优先级, 还有 代码在运行前已经编译完毕, 后续会按先前编译的初始化环境赋值
2.. 变量声明提示问题, 运行前环境: AO :{ 有 var aa, function aa (){} } 这两个同名的变量提升, 函数优先级高于普通变量, 且是整体提升,
3.. 函数变量提升, if 中定义 变量和函数,现在标准不允许.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
a = 100; function demo(e){ function e(){}; arguments[0] = 2; console.log(e); if(a){ var b = 123; function c(){}; } var c; a = 10; var a; console.log(b); f = 123; console.log(c); console.log(a); } var a; demo(1); console.log(a); console.log(f);
4.. 优先级考点: MDN https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
window.a || ( windw.a = '1' ) 这个先算括号()里面的 , 再算 || , 即: 先赋值 window.a ='1', 再判断 || 左侧window.a 为真 返回, window.a 为'1'
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
window.a || ( window.a = '1' ) console.log( window.a )
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
下面是按从最高到最低的优先级列出JavaScript运算符。具有相同优先级的运算符按从左至右的顺序求值。 运算符 描述 . [] () 字段访问、数组下标、函数调用以及表达式分组 ++ -- - ~ ! delete new typeof void 一元运算符、返回数据类型、对象创建、未定义值 * / % 乘法、除法、取模 + - + 加法、减法、字符串连接 << >> >>> 移位 < <= > >= instanceof 小于、小于等于、大于、大于等于、instanceof == != === !== 等于、不等于、严格相等、非严格相等 & 按位与 ^ 按位异或 | 按位或 && 逻辑与 || 逻辑或 ?: 条件 = oP= 赋值、运算赋值 , 多重求值 圆括号可用来改变运算符优先级所决定的求值顺序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
下面的表将所有运算符按照优先级的不同从高到低排列。 优先级 运算类型 关联性 运算符 20 圆括号 n/a ( … ) 19 成员访问 从左到右 … . … 需计算的成员访问 从左到右 … [ … ] new (带参数列表) n/a new … ( … ) 函数调用 从左到右 … ( … ) 18 new (无参数列表) 从右到左 new … 17 后置递增(运算符在后) n/a … ++ 后置递减(运算符在后) … -- 16 逻辑非 从右到左 ! … 按位非 ~ … 一元加法 + … 一元减法 - … 前置递增 ++ … 前置递减 -- … typeof typeof … void void … delete delete … await await … 15 幂 从右到左 … ** … 14 乘法 从左到右 … * … 除法 … / … 取模 … % … 13 加法 从左到右 … + … 减法 … - … 12 按位左移 从左到右 … << … 按位右移 … >> … 无符号右移 … >>> … 11 小于 从左到右 … < … 小于等于 … <= … 大于 … > … 大于等于 … >= … in … in … instanceof … instanceof … 10 等号 从左到右 … == … 非等号 … != … 全等号 … === … 非全等号 … !== … 9 按位与 从左到右 … & … 8 按位异或 从左到右 … ^ … 7 按位或 从左到右 … | … 6 逻辑与 从左到右 … && … 5 逻辑或 从左到右 … || … 4 条件运算符 从右到左 … ? … : … 3 赋值 从右到左 … = … … += … … -= … … *= … … /= … … %= … … <<= … … >>= … … >>>= … … &= … … ^= … … |= … 2 yield 从右到左 yield … yield* yield* … 1 展开运算符 n/a ... … 0 逗号 从左到右 … , …
5.. if ( function b () {} ){
typeof b }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
function b () {} 这个外面加括号 () 就变在了 函数表达式, 就会忽略掉函数名b, 值是 undefined var fn = function ffn (){} typeof ffn "undefined"
6.. var str = 'abcde' ; str.text = 'aabb' ; console.log( str.text ) ;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
字符串str.text赋值aabb, 隐式过程是: 转成包装类 new String(str).text='aabb' , 但是没变量接收保存, 就会被删除回收了, 等于没赋值, 还是undefined, 如果想要保存, 可 使用 包装类, 即: var str = new String( 'aabb' ), str.text = '1111'; consloe.log( str.text ) ;
7.. function foo (x) { console.log(arguments) ; return x }(1, 2, 3, 4, 5) 结果::
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
函数声明后不能直接跟执行符号()
否则会被解析为, 一个是函数声明,一个是另一个括号表达式,两者没关系
8.. 用css实现开关切换效果 , 注意点如下:
8.1 使用input框, 需要去除浏览器的内核默认渲染, -webkit-appearance : none ; ( 有兼容问题, 需要查MDN, 移动端这个可用 )
8.2 使用伪类 :checked ( 选中状态的单选或多选框 ) 和 :before , 例: 先后顺序: input:checked:before { left: 40px }
8.3