【JS基础】初学者不再担心,完全攻克JS读取同名变量的优先级判断

说明

在刚开始学习JS的时候,经常被同名变量的优先级判断面试题搞蒙了,也尝试过使用流行的优先级口诀去解决这些问题

变量申明 > 普通函数 > 函数传参 > 变量提升

但对于自己来说,只要是死记硬背的东西都会记不住,时间久了遇到有可能还会出现懵逼的情况。对于JS的初学者来说,我觉得这类问题还是要靠理解的思路去解决,才记得牢。

以下列举几个题目,并放上自己不严谨的解题思路,希望有错误大家都能及时的指出,也能让其他正在学习的小白一起科学的攻克这类问题。


变量的提升

变量的提升是在一个作用域内的代码开始执行时,会先把var声明的变量名提升到作用域的最顶部去(本次变量的提升只针对es5的var)。例如:

function fn(){
	console.log(bar);
	var bar = 1;
}

// 实际会是这个样子

function fn(){
    var bar // 变量提升上来了,但是只有声明并没赋值
	console.log(bar); // 从上往下执行到这句 undefined
	var bar = 1;
}

函数传参

function fn(bar){
	console.log(bar); 
	var bar = 1;
}
fn(5) // 本来变量提升是undefined,结果传入参数,就有值了

// 实际上

function fn(bar){
    var bar // 此时有参数传入,让只声明的变量知道值了
	console.log(bar); // 从上往下执行到这句 5
	var bar = 1;
}

函数的提升

先提两个函数定义的概念:

  1. 函数声明(式):function fn(){}
  2. 函数表达式 var fn = function(){}

函数声明(式)

一个作用域中的函数声明(式)会在代码执行前,提升到仅次于变量提升的位置,且相同名称的函数声明(式)一定是后者覆盖前者。例如:

function fn(bar){
	console.log(bar);
	function bar(){ //相同名称的函数
		return '函数1';
	}
	console.log(bar);
	var bar = 1;
	function bar(){ //相同名称的函数
		return '函数2';
	}
}
fn(5)

// 实际是这样

function fn(bar){
    var bar // 变量提升 , 传参赋值5
    function bar(){  // 函数变量提升,其实也就是变量提升,把bar = 5 覆盖
		return '函数2';
	}
	console.log(bar); // 从上往下执行到这句 直接把bar函数2整个代码打印出来
	console.log(bar); // 从上往下执行到这句 直接把bar函数2整个代码打印出来
	var bar = 1;
}

函数表达式

注意:函数声明(式)和函数表达式是有区别的!

function bar(){ 
	return '函数1';
}
// 不同于
var bar = function(){
	return '函数1';
}

例如:

function fn(bar){
	var bar = 1;
	var bar = function(){
		return '函数1';
	}
	console.log(bar);
	function bar(){
		return '函数2';
	}
}
fn(5);

 // 实际上
 
function fn(bar){
    var bar // 变量提升 传入参数赋值 bar=5
    function bar(){  // 函数提升 bar = 这个函数
		return '函数2';
	}
	var bar = 1;  // 从上到下执行到这里 bar被重新声明并赋值 bar = 1
	var bar = function(){  // 注意注意! 这里也是变量的赋值声明, bar = 这个函数
		return '函数1';
	}
	console.log(bar);  //  从上到下执行到这里,直接把bar函数1整个代码打印出来
}


小练习

来来来,做点练习巩固一下

习题一:

console.log(a) // 打印出个啥?
function a(){
	return '芜湖'
}
var a = 1

习题二:

alert(a)
a()
var a = 3;
function a() {
	alert(10)
}
alert(a)
a = 6;
a();

//什么?你说这题又懵了?别急再分析一下**************************

var a // 老规矩,变量提升一波 undefined
function a() { // 有名函数提升 a = 这个函数
	alert(10)
}

alert(a) // 是不是就弹出出上面函数的代码啦?

a() // 到这里a还是那个函数,直接执行,弹出10

var a = 3; // 芜湖,a变量声明赋值了 a=3

alert(a) // 是不是就弹出3了

a = 6; // a被重新赋值为6 a=6

a(); // 一个非函数怎么执行?直接报错

习题三:

alert(a)
// a() 如果这题作对了,把这句取消注释再试试
var a = 3; 
var a = function() { 
	alert(10)
}
alert(a)
a = 6;
a();

// 这题需要解析就给我评个论哈哈!

习题四:

var foo = function(){
	console.log(1);
}

function foo(){
	console.log(2);
}

foo();

习题五:

function fn() {
    var b = 1;
	function a() {
		console.log('1', b);
		var b = 2;
		console.log('2', b);
	}
	a();
	console.log('3', b);
}
fn();

// 这题解析一下吧

function fn() {
     var b // 不说了吧
     function a() {
        var b // 在这个函数作用域内变量提升 undefined
		console.log('1', b); // 打印 1 undefined
		var b = 2; // 声明赋值 b = 2
		console.log('2', b); // 打印 2 2
	}
    var b = 1; 
	a(); // 执行a函数,去看看a函数有啥
	console.log('3', b); // 这个b不是函数a内的哦,打印 3 1
}

习题六:这题比较复杂,需要JS基础稍微扎实一些(当然,不懂也没啥事,可以跳过)

function Foo() {
	getName = function() {
		console.log(1)
	}
	return this;
}
Foo.getName = function() {
	console.log(2)
}
Foo.prototype.getName = function() {
	console.log(3)
}
var getName = function() {
	console.log(4)
}
function getName() {
	console.log(5)
}

Foo.getName()
getName()
Foo().getName()
getName()
new Foo.getName()
new Foo().getName()
new new Foo().getName()
// 问:执行结果的顺序是怎么样的?

****************步骤解答

function Foo() { // 给window对象绑定一个函数Foo
	getName = function() { 
		console.log(1)
	}
	return this;
}
Foo.getName = function() { // 给函数Foo添加一个属性getName,是个函数
	console.log(2)
}
Foo.prototype.getName = function() {  //给函数Foo的原型添加一个属性getName,是个函数
	console.log(3)
}
var getName = function() { // 给window对象绑定一个对象,是个函数
	console.log(4)
}

function getName() { // 一个有名函数getName,默认提升,然后又被var getName声明覆盖了
	console.log(5)
}


Foo.getName();// 执行Foo上的getName属性 -------2
getName();//执行window对象上的getName --------4
Foo().getName(); //先执行了Foo,把window对象的getName修改了,然后返回this,指向window,也就是window.getName() -------1
getName(); //--------1
new Foo.getName(); //.点的优先级比new运算符高,new (Foo.getName)() --------2
new Foo().getName(); //()执行优先级比.高,所以(new Foo()).getName(),this指向构造函数的实例,所以是执行原型上的getName -------3
new new Foo().getName(); //同理,new [【new Foo()】.getName()] ----------3

习题七:从掘金哪里看来的,挺不错的题

var foo = function () {
    console.log("foo1")
}
foo()

var foo = function () {
    console.log("foo2")
}
foo()


function foo() {
    console.log("foo1")
}
foo()

function foo() {
    console.log("foo2")
}
foo()

尾巴

初学者学这块的时候其实完全没必要担心时间久了记不住,因为在真正工作中,基本遇不到因为同名变量引起的不好影响,谁没事会在同一个作用域里声明这种东西。大多数都是面试出的题罢了,所以能理解变量提升、函数提升就可以了哈。

大伙来个赞呗~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值