经典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
var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
  var name = 'Jack';
  console.log('Goodbye ' + name);
} else {
  console.log('Hello ' + name);
}
})();
// Goodbye Jack

var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
        let name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();
// Hello Tom

暂时性死区:
报错的区别

function test1() {
    test2()
}
function test2() {
    test1()
}
test1() // Uncaught RangeError: Maximum call stack size exceeded

假如不存在提升这个情况,那么就实现不了上述的代码,因为不可能存在 test1 在 test2 前面然后 test2 又在 test1 前面。

let a = function test1() {
    test2()
}
let b = function test2() {
    test1()
}
a() // Uncaught ReferenceError: test2 is not defined
  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函数作用域
var name = 'in window'
var obj = {
    name: "in obj",
    getName: function() { return this.name }
}
console.log(obj.getName());
console.log((obj.getName)());
console.log((obj.getName = obj.getName)());
// in obj
// in obj
// in window 相当于react事件没有绑定this当情况
// 即
// this.handleClick = this.handleClick.bind(this);
// button = <LogoutButton onClick={this.handleLogoutClick} />;
  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 3 5 9 11 10 12
console.log('script start')

async function async1() {
  await async2()
  console.log('async1 end')
}
async function async2() {
  console.log('async2 end')
}
async1()

setTimeout(function() {
  console.log('setTimeout')
}, 0)

new Promise(resolve => {
  console.log('Promise')
  resolve()
})
  .then(function() {
    console.log('promise1')
  })
  .then(function() {
    console.log('promise2')
  })

console.log('script end')
// script start => async2 end => Promise => script end => promise1 => promise2 => async1 end => setTimeout
  1. 引用类型
function test(person) {
  person.age = 26
  person = {
    name: 'yyy',
    age: 30
  }

  return person
}
const p1 = {
  name: 'yck',
  age: 25
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?

在这里插入图片描述

  1. 两个小坑
var obj = {"key":"1","value":"2"};
    var newObj = obj;
    newObj.value += obj.key;
    console.log(obj.value); 
    // "21"

浅拷贝 + 字符串和

  1. 函数
var m = 1, j=k=0;
    function add(n){
        return n = n+1;
    }
    y = add(m);
    function add(n){
        return n = n + 3;
    }
    z=add(m);
    console.log(y + ',' + z);
// 4.4

这是一个函数变量提升的题目

  1. 类型,隐式转换
String('11') == new String('11'); 
String('11') === new String('11');

版权声明:本文为yuanfangyoushan原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。