1. console.log(typeof typeof typeof null)
- typeof null // object
- typeof object // "undefined" (字符串)
- typeof "undefined" // string
- 所以 console.log(typeof typeof typeof null) // string
2.
for (var i = 0; i < 3; i++) {
document.body.addEventListener('click', function(){console.log(i)})
}
// 点击页面输出 3次3
// 变量i是var声明的,在全局范围内有效,不会受限于块级作用域,而全局只有一个变量 i ,每一次循环,变量i的值都会发生改变,而console.log(i)的i 是指向全局的同一个i,所以当点击页面的时候输出的 i 是同一个i 值为3。
for (let i = 0; i < 3; i++) {
document.body.addEventListener('click', function(){console.log(i)})
}
// 点击页面输出 1 2 3
// 变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算
3.
输入aaa-bbb-ccc 输出 AaaBbbCcc
function toUpCaseStr (str) {
return str.replace(/-/g, ' ').replace(/\b\w+\b/g, function(word) {
return word.substring(0, 1).toUpperCase() + word.substring(1);
}).replace(/ /g, '')
}
toUpCaseStr('aaa-bbb-ccc') // AaaBbbCcc
// 两边的\b表示单词边界,开始的(\w+)表示一个单词,
// 如果 regexp 具有全局标志 g,那么 replace() 方法将替换所有匹配的子串
当然还有更好的办法!!
4.
var x = 10;
function a(y) {
var x = 20;
return b(y); // 调用执行 b 函数的时候,b 函数作用域链的第一个元素就确定了,包含对象:y:20, arguments: [20]
}
function b(y) {
return x + y
}
// b函数在声明时 [[Scope]] 就已经确定了, 包含对象:this, windows, documents, x:10, a
a(20) // 30
作用域链这个数组可以分成两部分
1.第一个元素就是本函数的变量对象 (在执行函数时确定本函数的变量对象)
2.[[Scope]]: 所有上层上下文的链 (创建函数时该函数的 [[Scope]] 就确定了)
记得JS权威指南中有一句很精辟的描述: ”JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.”
网友评论