this指向,作用域,闭包,原型链

this:关键字

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁。

情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,严格模式下指向undefined。

function a(){
    var user = "白白";
    console.log(this.user); //undefined
    console.log(this); //Window
}
a();

情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

var o = {
    user:"白白",
    fn:function(){
        console.log(this.user);  //白白
    }
}
o.fn();

情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。

var o = {
    user:"白白",
    fn:function(){
        console.log(this.user); //白白
    }
}
window.o.fn();

情况4:

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window。


当this碰到return时:

若return的是基本类型或者null时,this指向函数的实例;

但若return对象时,this指向这个对象。


作用域:

储存变量的良好规则,之后可以方便的找到这些变量。

负责收集并维护所以声明的变量组成的一系列查询,并实施一套非常严格的规则,确定当前执行的带卡对这些变量的访问权限。

ES5中只有全局和函数作用域,无块级作用域(ES6新,let,const有关)。


作用域链:

作用域 即:一量在自己的作用域中没有,那么它会找父的,直到最顶层程如下:

· 任何在行上下文刻的作用域都由作用域实现

· 在一个函数被定, 会将它定义时刻的scope chain链接到这个函数对象的[[scope]]属性

提升:

函数和变量声明都会被提升(var),但函数首先会被提升,然后是变量。

      var getName = function(){
        console.log(2);
      }
      function getName() {
        console.log(1);
      }
      getName();  //2
      foo();  //function 函数先被提升,所以取到了函数
      var foo;
      function foo(){
        console.log("function");
      }
      foo = function(){
        console.log("foo = ");
      }
      foo();  //foo = ,但在函数之后foo()被foo = 覆盖

将变量声明提升到它所在的作用域的最开始。

1.函数体内同名的局部变量或参数的优先级高于全局

2.不用var的均为全局变量,无论在哪里

3.只有函数声明才存在函数提升


闭包:

闭包就是能够读取其他函数内部变量的函数。

如果某个函数被他的父函数之外的一个变量引用,就会形成闭包。

作用:

个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

闭包的作用,就是保存自己私有的变量,通过提供的接口(方法)给外部使用,但外部不能直接访问该变量

缺点:

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。


例子(使用闭包):

 
复制代码
var test=(function(){
  var a=0;
  return function(){
    ++a
    console.info(a);
}
})()
test();//  1
test();//  2
test();//  3
复制代码

 

例子(不使用闭包):

复制代码
var test=function(){
  var a=0;
  ++a
  console.info(a);
 
}
test();// 1
test();// 1
test();// 1
复制代码

上面例子形成了闭包,函数被全局调用,函数第一次执行完后,作用域没有被回收机制销毁,所以变量a也被保存下来了,每次调用test,执行后a都会自加1。如果没有形成闭包,每次调用test,执行后a都会销毁染后重新创建,执行结果都为1.

闭包的应用:

1)结果缓存:

我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。

2)封装:

使函数内部的变量外部不可直接访问。

3)实现类和继承:

我们定义一个函数,它就像一个类,我们new一个该函数对象,访问它的方法。

4)ajax的闭包:

需要一个能长期保存下来的变量来确定前一个ajax请求是否完成

设置一个变量长期存储在内存中,判断当前是否在处理ajax请求。(在处理中判断修改变量的值)

原型,原型链

javascript中一切皆对象,每个对象都有一个__proto_ 属性(由浏览器自动创建),该属性指向它原型。当一个对象在查找一个属性的时,自身没有就会根据__proto__ 向它的原型进行查找,如果都没有,直到查到Object.prototype._proto_为null,这样也就形成了原型链。


那prototype又是什么?!我们知道可以通过构造函数来创造一个类,prototype的作用就是,让类的属性可以被继承。所以只有构造函数才会有prototype这个属性。


实例对象的__proto__指向构造函数.prototype,构造函数.prototype.constructor指向构造函数本身,构造函数.prototype的__proto__指向Object的prototype,Object的prototype的__proto__指向null


判断原型的方法:

instanceof和type of

instanceof用来测试一个对象在其原型链中是否存在一个构造函数的prototype属性。

A(要检测的对象) instance B(某个构造函数) 实现:

var L = A.__proto__; //从A的__proto__向上找
var R = B.prototype;//从A的__proto__向上找
if(L == R){
    return ture; //能找到就返回ture
}

type of:

 一个值使用typeof操作符会返回下列字符串:

             1.Undefinde

             2.Functon    如果值是函数

             3.Number

             4.String

             5.Boolean

             6.Object     如果值是对象或null



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值