js几个经典的题目详解
直接看题目,先不要急着看答案 先自己思考,收获更多
一
var out = 25,
inner = {
out: 20,
func: function () {
var out = 30;
return this.out;
}
};
console.log((inner.func, inner.func)());
console.log(inner.func());
console.log((inner.func)());
console.log((inner.func = inner.func)());
25,20,20,25
代码解析:这道题的考点分两个
1.作用域
2.运算符(赋值预算,逗号运算)
先看第一个输出:25,因为(inner.func, inner.func)是进行逗号运算符,逗号运算符就是 运算前面的,
返回最后一个,举个栗子
var i=0,j=1,k=2;
console.log((i++,j++,k))//返回的是k的值 2 ,如果写成k++的话 这里返回的就是 3
console.log(i);//1
console.log(j);//2
console.log(k);//2
回到原题(inner.func, inner.func)就是返回inner.func而inner.func只是一个匿名函数
function () {
var out = 30;
return this.out;
}
而且这个匿名函数是属于window的
则变成了
(function () {
var out = 30;
return this.out;
})()
此刻的this--》window
所以out 是25
第二和第三个console.log的作用域都是 foo,也就是他们执行的其实是
foo.func();
foo作用域中是有out变量的,所以结果是20
第四个console.log
考查的是一个等号运算inner.func = inner.func 其实返回的是运算的结果,
举个栗子
var a=2,b=3;
console.log(a=b)//输出的是3
所以inner.func = inner.func 返回的也是一个匿名函数
function () {
var out = 30;
return this.out;
}
此刻 道理就和第一个console.log一样了 输出的结果是 25
二
if (!("a" in window)) {
var a = 1;
}
alert(a);
代码解析:如果window不包含属性a,就声明一个变量a,然后赋值为1。
你可能认为alert出来的结果是1,然后实际结果是“undefined”。要了解为什么,
需要知道JavaScript里的3个概念。
首先,所有的全局变量都是window的属性,语句 var a = 1;等价于window.a = 1;
你可以用如下方式来检测全局变量是否声明:"变量名称" in window
第二,所有的变量声明都在范围作用域的顶部,看一下相似的例子:
alert("b" in window);
var b;
此时,尽管声明是在alert之后,alert弹出的依然是true,这是因为JavaScript引擎
首先会扫墓所有的变量声明,然后将这些变量声明移动到顶部,最终的代码效果是这样的:
var a;
alert("a" in window);
这样看起来就很容易解释为什么alert结果是true了。
第三,你需要理解该题目的意思是,变量声明被提前了,
但变量赋值没有,因为这行代码包括了变量声明和变量赋值。
你可以将语句拆分为如下代码:
var a; //声明
a = 1; //初始化赋值
当变量声明和赋值在一起用的时候,JavaScript引擎会自动将它分为两部以便将变量声明提前,
不将赋值的步骤提前是因为他有可能影响 代码执行出不可预期的结果。
所以,知道了这些概念以后,重新回头看一下题目的代码,其实就等价于:
var a;
if (!("a" in window)) {
a = 1;
}
alert(a);
这样,题目的意思就非常清楚了:首先声明a,然后判断a是否在存在,如果不存在就赋值为1,
很明显a永远在window里存在,这个赋值语 句永远不会执行,所以结果是undefined。
提前这个词语显得有点迷惑了,你可以理解为:预编译。
三
var a = 1;
var b = function a(x) {
x && a(--x);
};
alert(a);
这个题目看起来比实际复杂,alert的结果是1;这里依然有3个重要的概念需要我们知道。
首先,在题目1里我们知道了变量声明在进入执行上下文就完成了;第二个概念就是函数声明也是提前的,
所有的函数声明都在执行代码之前都已经完成了声明,和变
量声明一样。澄清一下,函数声明是如下这样的代码:
function functionName(arg1, arg2){
//函数体
}
如下不是函数,而是函数表达式,相当于变量赋值:
var functionName = function(arg1, arg2){
//函数体
};
澄清一下,函数表达式没有提前,就相当于平时的变量赋值。
第三需要知道的是,函数声明会覆盖变量声明,但不会覆盖变量赋值,为了解释这个,我们来看一个例子:
function value(){
return 1;
}
var value;
alert(typeof value); //"function"
尽快变量声明在下面定义,但是变量value依然是function,也就是说这种情况下,
函数声明的优先级高于变量声明的优先级,但如果该 变量value赋值了,那结果就完全不一样了:
function value(){
return 1;
}
var value = 1;
alert(typeof value); //"number"
该value赋值以后,变量赋值初始化就覆盖了函数声明。
重新回到题目,这个函数其实是一个有名函数表达式,函数表达式不像函数声明一样可以覆盖变量声明,
但你可以注意到,变量b是包含了该函数表达式,而该函数表达式的名字是a;不同的浏览器对a这个名
词处理有点不一样,在IE里,会将a认为函数声明,所以它被变量初始 化覆盖了,就是说如果调用a(–x)的
话就会出错,而其它浏览器在允许在函数内部调用a(–x),因为这时候a在函数外面依然是数字。
基本上,IE里调用b(2)的时候会出错,但其它浏览器则返回undefined。
理解上述内容之后,该题目换成一个更准确和更容易理解的代码应该像这样:
var a = 1,
b = function(x) {
x && b(--x);
};
alert(a);
这样的话,就很清晰地知道为什么alert的总是1了。
四
function a(x) {
return x * 2;
}
var a;
alert(a);
这个题目比较简单:即函数声明和变量声明的关系和影响,遇到同名的函数声明,不会重新定义
五
4、function b(x, y, a) {
arguments[2] = 10;
alert(a);
}
b(1, 2, 3);
关于这个题目,ECMAsCRIPT 262-3的规范有解释的。
活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。
arguments属性的值是Arguments对象.
关于 Arguments对象的具体定义,看这里:ECMAScript arguments 对象
六
function a() {
alert(this);
}
a.call(null);
这个题目可以说是最简单的,也是最诡异的!关于这个题目,我们先来了解2个概念。
这个问题主要考察 Javascript 的 this 关键字,具体看这里:
关于Javascript语言中this关键字的用法
关于 a.call(null); 根据ECMAScript262规范规定:如果第一个参数传入的对象调用者是null
或者undefined的话,call方法将把全局对象(也就是window)作为this的值。所以,
不管你什么时候传入null,其this都是全局对象window,所以该题目可以理解成如下代码:
function a() {
alert(this);
}
a.call(window);
所以弹出的结果是[object Window]就很容易理解了。
七
var a={}, b={key:'b'}, c={key:'c'};
a[b]=123; a[c]=456;
console.log(a[b]);//456
原因:当使用一个引用类型·当做某个对象的属性来赋值,都会隐式的调用toString()方法
在执行a[b] = 123的时候,会用b作key,而b是个对象,实际执行的是a[b.toString()] = 123,即a['[object Object]'] = 123,
同理执行a[b] = 456时,实际执行的是a[c.toString()] = 456,即a['[object Object]'] = 456
由于b.toString()和c.toString()都等于'[object Object]',等于在同一个key上赋值了,后者覆盖了前者,所以为456.
js几个经典的题目详解的更多相关文章
- javascript常用经典算法实例详解
javascript常用经典算法实例详解 这篇文章主要介绍了javascript常用算法,结合实例形式较为详细的分析总结了JavaScript中常见的各种排序算法以及堆.栈.链表等数据结构的相关实现与 ...
- 最详尽的 JS 原型与原型链终极详解,没有「可能是」。(一)
最详尽的 JS 原型与原型链终极详解,没有「可能是」.(一) 第二篇已更新,点击进入第三篇已更新,点击进入
- JS中的函数节流throttle详解和优化
JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...
- Node.js中环境变量process.env详解
Node.js中环境变量process.env详解process | Node.js API 文档http://nodejs.cn/api/process.html官方解释:process 对象是一个 ...
- 转载 JS组件Bootstrap Select2使用方法详解
JS组件Bootstrap Select2使用方法详解 作者:懒得安分 字体:[增加 减小] 类型:转载 时间:2016-01-26我要评论 这篇文章主要为大家介绍了JS组件Bootstrap Sel ...
- js replace 与replaceall实例用法详解
这篇文章介绍了js replace 与replaceall实例用法详解,有需要的朋友可以参考一下stringObj.replace(rgExp, replaceText) 参数 stringObj 必 ...
- JS DOM对象控制HTML元素详解
JS DOM对象控制HTML元素详解 方法: getElementsByName() 获取name getElementsByTagName() 获取元素 getAttribute() 获取元素 ...
- JS JSOP跨域请求实例详解
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题.这篇文章主要介绍了JS JSOP跨域请求实例详解的相关资料,需要的朋友可以参考下 ...
- js课程 1-3 Javascript变量类型详解
js课程 1-3 Javascript变量类型详解 一.总结 一句话总结:js对象点(属性方法),json对象冒号(属性方法).属性和方法区别只有一个括号. 1.json对象中的函数的使用? 函数名 ...
随机推荐
- easyui 布局之window和panel一起使用时,拉动window宽高时panel不跟随一起变化
项目开发中布局是每一个组件都由最外层的window和内部的至少一个panel组成,其他的细小组件再依次放到panel中. 问题:当拉动外部的window时我们希望内部的panel的宽高也跟着变化,但是 ...
- ajax请求数据时什么时候用GET,什么时候用POST
GET的目的就如同其名字一样是用于获取信息的.它旨在显示出页面上你要阅读的信息.浏览器会缓冲GET请求的执行结果,如果同样的GET请求再次发出,浏览器就会显示缓冲的结果而不是重新运行整个请求.重新请求 ...
- G: Dave的时空迷阵(next数组)
G: Dave的时空迷阵 Time Limit: 1 s Memory Limit: 128 MB Submit My Status Problem Description 皇家理工本部隐藏 ...
- Vue.js货币格式化函数
函数: const digitsRE = /(\d{3})(?=\d)/g export function currency (value, currency, decimals) { value = ...
- Android Https双向认证 + GRPC
keywords:android https 双向认证android GRPC https 双向认证 ManagedChannel channel = OkHttpChannelBuilder.for ...
- 全球免费公共 DNS 解析服务器 IP 地址列表推荐 (解决无法上网/加速/防劫持)
除了宽带提供商的 DNS 以外,像阿里云.腾讯云.Google.百度.IBM.CNNIC 等一些有足够实力的大型互联网公司也非常慷慨地为公众提供了免费的 DNS 解析服务器.异次元这就搜集了全球范围内 ...
- 小改造gotty,使之适合接收经过一层加密的URL
当然,比起密码设置,这个安全性也不是特别高, 但比起直接传参数. 还是要专业一些的. 其实现思路分两种: 第一种是在gotty.js之内加入解url的函数. 第二种在是go源代码时,加入同等的解密函数 ...
- javascript 中 x offsetX clientX screenX pageX的区别
在javascript的事件对象中的关于事件鼠标位置的几个属性(x, pageX, offsetX, scrrenX clientX)及(y, pageY, offsetY, screenY, cli ...
- [转] Lodash
与underscore 类似 , 是1个js库,内部封装了诸多对字符串.数组.对象等常见数据类型的处理函数. 模块组成 Lodash 提供的辅助函数主要分为以下几类,函数列表和用法实例请查看 Loda ...
- javaScript事件(七)事件类型之键盘与文本事件
键盘事件如下: keydown:当用户按下键盘上的任意键时触发,而且如果按住不放的话,会重复触发此事件. keypress:当用户按下键盘上的字符键时触发,而且如果按住不放的话,会重复触发此事件. k ...