经典js代码题目求输出

  1. let var 作用域
function foo() {
		console.log(this.num)
	}
	var num = 4;
	foo(); // 4
let name = "John";
function sayHi() {
  alert("Hi, " + name); 
}
name = "Pete";
sayHi(); // pete
function makeWorker() {
  let name = "Pete";
  return function() {
    alert(name);
  };
}
let name = "John";
// 创建一个函数
let work = makeWorker();

work(); // Pete
  1. this 箭头函数 自行函数 普通函数 对象 构造函数
  • 在普通函数下,谁调用这个函数,this指向谁。
  • 而箭头函数没有 this,它会从自己的作用域链的上一层继承 this(因此无法使用 apply / call / bind 直接修改 this 值, 可以改变作用域中this的指向可以改变箭头函数的this,eg. function closure(){()=>{//code }},在此例中,我们通过改变封包环境closure.bind(another)(),来改变箭头函数this的指向)。
var name = 'window'

var person1 = {
  name: 'person1',
  show1: function () {
    console.log(this.name)
  },
  show2: () => console.log(this.name),
  show3: function () { //自行函数
    return function () {  
      console.log(this)
    }
  },
  show4: function () {
    return () => console.log(this.name)
  }
}
var person2 = { name: 'person2' }
person1.show1() // person1,隐式绑定,this指向调用者 person1 
person1.show1.call(person2) // person2,显式绑定,this指向 person2

person1.show2() // window,箭头函数绑定,this指向外层作用域,即全局作用域
person1.show2.call(person2) // window,箭头函数绑定,this指向外层作用域,即全局作用域

person1.show3()() // window,默认绑定,这是一个高阶函数,
				  // 实际调用者是window 如果是严格模式,这里的this就是undefined了
				  // 类似于`var func = person1.show3()` 执行`func()`
person1.show3().call(person2) // person2,显式绑定,this指向 person2
person1.show3.call(person2)() // window,默认绑定,调用者是window

person1.show4()() // person1,箭头函数绑定,this指向外层作用域,即person1函数作用域
person1.show4().call(person2) // person1,箭头函数绑定,
							  // this指向外层作用域,即person1函数作用域
person1.show4.call(person2)() // person2
var name = 'window'

function Person (name) {
  this.name = name;
  this.show1 = function () {
    console.log(this.name)
  }
  this.show2 = () => console.log(this.name)
  this.show3 = function () {
    return function () {
      console.log(this.name)
    }
  }
  this.show4 = function () {
	  
    return () => console.log(this.name)
  }
}
personA.show1() // personA,隐式绑定,调用者是 personA
personA.show1.call(personB) // personB,显式绑定,调用者是 personB

personA.show2() // personA,首先personA是new绑定,产生了新的构造函数作用域,
				// 然后是箭头函数绑定,this指向外层作用域,即personA函数作用域
personA.show2.call(personB) // personA,同上

personA.show3()() // window,默认绑定,调用者是window
personA.show3().call(personB) // personB,显式绑定,调用者是personB
personA.show3.call(personB)() // window,默认绑定,调用者是window

personA.show4()() // personA,箭头函数绑定,this指向外层作用域,即personA函数作用域
personA.show4().call(personB) // personA,箭头函数绑定,call并没有改变外层作用域,
							  // this指向外层作用域,即personA函数作用域
personA.show4.call(personB)() // personB,解析同题目1,最后是箭头函数绑定,
							  // this指向外层作用域,即改变后的person2函数作用域
  1. 引用类型 闭包
	function Foo() {
		var i = 0;
		return function () {
			console.log(i++);
		}		
	}
	var f1 = Foo(),f2 = Foo();
	f1(); // 0
	f1(); // 1
	f2(); // 0

Function是引用类型,保存在堆中,变量f1,f2是保存在栈中
闭包:一个函数(产生新的作用域)定义的局部变量、子函数的作用域在函数内,但是一旦离开了这个函数,局部变量就无法访问,所有通过返回子函数到一个变量f1的方法,让f1指向堆中的函数作用域,这样可以使用局部变量i;f1 = Foo()的时候,创建了一个闭包,并将其作为函数定义的一部分,闭包里的值就是i,当前值为0
过程:

  • 第一次f1(): f1=Foo()中,先执行Foo(): i = 0,return值返回给f1(f1指向子函数 f1()=function(){…},因为子函数没有 定义i,所以向上找到父函数定义的 i: )并执行子函数 输出i=0,再自加 i =1(覆盖了父函数Foo 的 i值);

  • 第二次f1() : 执行的是子函数 Function(){ …},输出的是父函数 的 i=1,再自加 i =2;

  • 第一次f2(): 同第一次f1(),不同的是 f2指向堆中一个新的对象 function(){ …},所有此i非彼i,输出i=0

  • 如果再次f2(),那么和第二次f1(),一样输出i=1;

3.1.

let c = 4
const addX = x => n => n + x
const addThree = addX(3)
let d = addThree(c)
console.log('example partial application', d) // 7

3.2 然后引出一个常见的闭包题目,正确的输出0123…

for (var i = 0; i < 4; i++) {
    setTimeout(function() {
      console.log(i);
    }, 300);
  } // 4444

  for( var i = 0; i < 4; i ++) {
     (function (i) {
      setTimeout(function() {
        console.log(i);
      }, 300);
    })(i);
  } // 0123 // 自行函数,每次相当于都是一个新的Foo()

  for (var i = 0; i < 4; i++) {
    setTimeout(
      (function() {
        console.log(i);
      })(i)
      , 300);
  } // 0123
  1. js执行顺序
console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})
// 1 7 6 8 2 4 5 9 11 12

你可能感兴趣的:(面试,前端,JS)