var的作用域
百度一面
var res = []
var a = 3
var total = 0
function foo(a){
for(var i = 0; i < 3; i++){
res[i] = function(){
total += i * a
console.log(total)
}
}
}
foo(1)
res[0]() // 3
res[1]() // 6
res[2]() // 9
主要就是var作用域的一个考察。
在foo(1)处,传入了一个参数a = 1,因此下面的res[i]执行时会首先找到这个a并使用它。
res[i]并没有将i作为参数传入到函数中,因此执行时会去foo中找i,而i经过循环后变成了3,所以每次 i * a都是 1 * 3,total就从3 到 6 再到 9.
去哪儿二面
function print(n){
for(var i = 0; i < n; i++){
setTimeout(console.log, 1000, i) //这种写法第一个参数是回调函数,第二个参数是等待时间,第三个参数是回调函数的参数
}
}
print(10)
// 1秒后输出0到9
function print(n){
for(var i = 0; i < n; i++){
setTimeout(console.log, 1000 * i, i)
}
}
print(10) //每隔一秒输出一个
\\ 0
\\ 1
\\ 2
\\ 3
\\ 4
\\ 5
\\ 6
\\ 7
\\ 8
\\ 9
如何将上面每一秒输出一个数字的代码改为promise实现,代码如下
function print(n){
for(var i = 0; i < n; i++){
myPromise(i);
}
}
function myPromise(i){
return new Promise((resolve, )=>{
setTimeout(()=>{
console.log(i)
resolve()
}, 1000*i)
})
}
变量与函数提升
变量提升:JS 解析器会把 var 声明的变量提升到,当前作用域最前面(只提升声明,不提升赋值);
函数提升:把 function 关键字声明的函数(命名函数)提升,当前作用域最前面; (只提升声明,不提升执行)
- 函数声明会优先于var变量声明
- 同一作用域下存在多个同名函数声明,后面的会替换前面的函数声明
作用域:es6之前是全局作用域和函数作用域,ed6增加了块级作用域,但只有let和const会产生块级作用域
函数与变量同名案例
console.log(a); //f a(){console.log('funA')}
var a = 'varA';
console.log(a); // varA
function a() {
console.log('funA');
}
a(); // error: a is not a function
//Example1
foo;
var foo = function () {
console.log('foo1');
}
foo(); //foo1
var foo = function () {
console.log('foo2');
}
foo();//foo2
//Example2
foo();
function foo() {
console.log('foo1');
}
foo();
function foo() {
console.log('foo2');
}
foo();
// foo2 foo2 foo2
函数提升优先级高于变量提升,且不会被同名变量声明时覆盖,但是会被同名变量赋值后覆盖。
function a() {}
var a = 1;
console.log(typeof a)// number
function a() {}
console.log(typeof a) //function
var a = 1;
案例1
var num = 10
fn()
function fn(){
console.log(num)
var num = 20
}
console.log(num)
以上代码经过变量和函数声明提升后为以下代码
var num
function fn(){
var num;
console.log(num) //这里输出的是fn内部的num
num = 20
}
num = 10
fn() //输出undefined
console.log(num) //输出全局num 10
案例2
var a = 18;
f1()
function f1() {
var b = 9
console.log(a)
console.log(b)
var a = '123'
}
变量和函数提升后相当于以下代码
var a
function f1() {
var b
var a
b = 9
console.log(a)
console.log(b)
a = '123'
}
a = 18
f1() // undefined 9
案例3 (典型面试题)
f1()
console.log(c)
console.log(b)
console.log(a)
function f1() {
var a = b = c = 9
console.log(a)
console.log(b)
console.log(c)
}
变量和函数提升后相当于以下代码
function f1() {
var a = 9; b = 9; c = 9 //b和c没有用var声明,因此是一个全局变量
console.log(a) //9
console.log(b) //9
console.log(c)//9
}
f1()
console.log(c) //9
console.log(b) //9
console.log(a) //报错:a is not defined
面试题(哪家的记不清了)
var a = 20;
function bar() {
console.log(a);
}
function foo(fn) {
var a = 10;
fn();
}
foo(bar); //20
相当于
var a;
function foo(bar) {
function bar() {
console.log(a);
}
var a;
fn();
a = 10
}
a = 20
foo(bar); //20
this指向
案例1 (富途笔试)
var a = 1
var b = 2
let obj = {
a: 3
b: 4
getA: function(){
var a = 5
setTimeout(function(){
console.log(this.a)
}, 0) // setTimeout(callback, t)这里的callback是回调函数,被全局调用,this指向windows。如果是箭头函数的话则this指向obj
}
getB: function(){
var b = 6
return function(){
console.log(this.b)
}()
}
}
obj.getA()
obj.getB() //getB执行后返回一个立即执行函数,而这个函数没有被其他对象调用,它的this指向windows
//输出 2 1(先输出的全局的b,再输出全局的a)
原型对象
原型对象中的this
原型对象中的this指向调用它的实例对象
function Book(){
this.type = 'English'
}
Book.prototype.getType = function(){
console.log(this.type)
}
book = new Book()
book.getType() // English
book.type = 'Math'
book.valueOf() // Book {type: 'Math'}
JavaScript 中的 valueOf() 方法用于返回指定对象的原始值,若对象没有原始值,则将返回对象本身。