预解析&&作用域&& this指向

定义:

        JavaScript”预解析”,可以理解为把变量或函数预先解析到它们被使用的环境中。

解析过程:

         第一步,会预先解析关键字var、function等

         第二步,提前赋值:

                1. var a = 10 提前解析 var a;(此时a的值为undefined)

                2. 函数,在正式运行代码前,赋值为整个函数块

console.log(fn)   //function变量提升   function fn(){console.log("123")}
function fn(){
   console.log("123")
}

        第三步,预解析结束后,浏览器再逐行解读代码;

//看看下面的代码输出结果
console.log(a) 
var a = 1;
//解析过程
var a;
console.log(a); //var变量提升   undefined
a = 1;

 解析过程: 

         预解析过程中,当变量和函数同名时:只留下函数的值,不管谁前谁后,所以函数优先级更高; 

console.log(fn)   //function变量提升   function fn(){console.log("123")}
var fn = 234;
function fn(){
   console.log("123")
}

 经典预解析面试题

console.log(a) 
var a=1;      
function a(){console.log(2)}  
console.log(a) 
var a=3;       
console.log(a) 
function a(){console.log(4)} 
console.log(a)
function fun ( n ) {
 console.log( n );
 var n = 456;
 console.log( n );
}
var n = 123;
fun( n );
答:123 456
 //解析过程
  //预解析
  var n;
  function fun(){};
  n = 123 //全局变量
  fun(n) 当执行fun(n),会执行函数体里的内容,此时fun函数会形成一个新的私有作用域
  //fun()内部解析过程
  //如果有形参,先给形参赋值
  var n = 123;
  //进行私有作用域中的预解析;
  var n;  
  //私有作用域中的代码从上到下执行
  console.log( n );  //123
  n = 456;
  console.log( n );  //456

作用域 

 定义:

        它是指对某一变量和方法具有访问权限的代码空间, 在JS中, 作用域是在函数中维护的。

        表示变量 或函数起作用的区域,指代了它们在什么样的上下文中执行,亦即上下文执行环境

         ES5的作用域只有两种:全局作用域和局部作用域 

 全局作用域

var a=1; //全局作用域
function fn1(){ 
   console.log(a)
};
fn1()

 局部作用域

function fn1(){
   var a=1;   //局部作用域
};
fn1();
console.log(a);

 全局变量和局部变量同名的坑

(1)在全局变量和局部变量不同名时,其作用域是整个程序。

(2)在全局变量和局部变量同名时,全局变量的作用域不包含同名局部变量的作用域。

var a=1;
function fn1(){ 
   console.log(a)
 var a = 2;
};
fn1();
console.log(a);

 经典作用域面试题

var a = 10;    
function f1(){    
 var b = 2 * a;    
 var a = 20; 
 var c = a+1;    
 console.log(b);     
 console.log(c);    
}    
f1()
var a=10;
function test(){
   console.log(a);      
   a=100;       
   console.log(this.a);     
   var a;      
   console.log(a); 
}
test();

 this指向

this是什么

1. this是Javascript语言的一个关键字。

2. 它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用,随着函数使用场合的不同,this的值会发生变化,指向是不确定的,也就是说是可以动态改变的;

3. 但是有一个总的原则,那就是this指的是,调用函数的那个对象。

 this有什么用?平时我们在哪里用到过

<ul>
   <li>1111</li>
   <li>2222</li>
   <li>3333</li>
   <li>4444</li>
 </ul>
   <script type="text/javascript">
     $("ul li").click(function() {
       $(this).css('color','#f00').siblings().css('color','#333');
     })
   </script>
// 这个是不是好熟悉,这是我们在用到Jquery时最多的处理方式,这里的this就是当前单击的li;
//这是我们接触到的最简单的this,用途相信很多同学都是理解的,但在实际的应用中this并不只是这么简单,还有其它的引用

1. 在简单函数中的使用

function test(){
 console.log(this) //window
};
test()
在这种情况下,因为代码不是运行在严格模式下, this 又必须是一个对象, 所以他的值默认为全局对象。
因为严格模式下,this的值为undefined
function test(){
 "use strict";     //严格模式
 console.log(this) //undefined
 };
test()

2、在对象的方法中使用

var obj = {}
   obj.a = 3;
     obj.fun = function(){
 return this.a;   // this表示当前o对象 当前的this.a 等价于 obj.a
     };
     console.log(obj.fun())
// 还有一些特殊的情况:
// 1)对象中调用外部函数
 var a = 1;
   function test() {
       return this.a;
   };
   var o = {}
   o.a = 3;
   o.b = test;
   console.log(o.b()) // 结果为3,因为当前test()中的this表示的是o对象


// 2)字面量方式中的this
   var o = {
       name:'sonia',
       bind:function() {
         return this.name;   // 当前this表示为o对象
       }
   };
   o.bind()

3、在构造函数中使用

所谓构造函数,就是通过这个函数生成一个新对象(object)。
当一个函数作为构造器使用时(通过 new 关键字), 它的 this 值绑定到新创建的那个对象。
如果没使用 new 关键字, 那么他就只是一个普通的函数, this 将指向 window 对象。


function Fun(name,age) {
       this.name = name;
       this.age = age;
};
var fun = new Fun('lili',22);
console.log(fun.name);

在上面的示例中, 有一个名为 Fun() 的构造函数。通过使用 new 操作符创建了一个全新的对象,名为fun。
同时还通传给构造函数参数, 作为新对象的name、age属性。
通过最后一行代码中可以看到这个字符串成功的打印出来了, 因为 this 指向的是新创建的对象, 而不是构造函数本身。 

 4、 如何改变this的指向

//apply() 方法接收两个参数: 第一个是要设置为 this 的那个对象, 第二个参数是可选的,如果要传入参数,则封装为数组作为 apply() 的第二个参数即可。
//call() 方法 和 apply() 基本上是一样的, 除了后面的参数不是数组, 而是分散开一个一个地附加在后面。
var num = 10;
function test(){
 return this.num;
};
var obj ={
 num : 5,
 fun:test
}
console.log(obj.fun.call(this))     //返回的值是10,当前的this表示全局对象
var num = 10;
function test(){
 return this.num;
};
var obj ={
 num : 5,
 fun:test
}
console.log(obj.fun.call(obj)) //返回值为5,当前的this为obj对象

常见面试题

var number = 1;
var obj = {
 number:2,
 showNumber:function(){
    this.number = 3;
    (function(){
     console.log(this.number);
     })();
     console.log(this.number);
  }
};
obj.showNumber();

答案是 1   3
由于showNumber方法的拥有者是obj,所以this.number=3; this 指向的就是 obj 的属性 number。
  同理,第二个 console.log 打印的也是属性 number。
   为什么第二点说一般情况下this都是指向函数的拥有者,因为有特殊情况。

函数自执行就是特殊情况,在函数自执行里,this 指向的是:window。所以第一个 console.log 打印的是 window 的属性number。
   所以要加一点: 在函数自执行里,this 指向的是 window 对象。

// 测试题:
var length = 100;
function f1() {
 console.log( this.length )
}
var obj = {
 x: 10,
 f2: function( f1 ){
   f1();
   arguments[0]();
 }
}
obj.f2(f1,1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值