原型和闭包

原型及原型链

    每个对象都有一个_propto_(隐式原型),指向创建该对象的函数的proptotype(原型)。

    Object.prototype的_proto_指向的是null。

    函数也是对象,函数也有_proto_,函数是Function创建的。因此,Object._proto_指向的时Function.prototype。(Object也是一个函数)

    既然Function也是一种对象,那么Function._proto_指向的是创建该对象(Function)的函数(Function)的Function.prototype。而Function.prototype._proto_指向的是Object.prototype。以上逻辑可自行分析。

    当访问一个对象的属性时,会先从基本属性中找,如果没有,则沿着_proto_这条链向上找,这就是原型链。

执行上下文环境及作用域

    执行上下文(或执行上下文环境)在准备阶段会完成以下工作:

    1.变量、函数表达式--变量声明,默认赋值为undefined

    2.this--赋值

    3.函数声明--赋值;

 

    javascript在执行一段代码前,会进行这些准备工作来生成执行上下文,这个代码段其实分三种情况:全局代码、函数体、eval代码。其中eval代码接收的也是一段文本形式的代码,例如:eval('alert(qwe)');函数体时代码段是因为函数在创建时,本质上是new Function(...)得来的,需要传入一个文本形式的参数作为函数体。

    全局代码的上下文环境数据内容为:

    1.普通变量(包括函数表达式)  ---声明

    2.函数声明    ---赋值

    3.this    ---赋值

    如果代码段是函数体,则再次基础上附加:

    1.参数    ---赋值

    2.arguments   ---赋值

    3.自由变量的取值作用域  ----赋值

    要给上下文环境下一个通俗定义:在执行代码前,把将要用到的所有变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。

this指针

    1.构造函数

    所谓构造函数,就是可以用来new对象的函数。注意,构造函数的第一个字母大写。如果函数作为构造函数使用,那么其中的this代表它即将new出来的对象,例如:function AA(){this.name='wewe'};var aa=new AA();aa();如果直接调用,this则指向windows,例如:AA()。

    2.函数作为对象的一个属性

    如果函数作为对象的一个属性,且作为对象的一个属性被调用时,this指向该对象,例如:var  obj={fax:function(){this.name='dsad'}};obj.fax();

    如果函数被赋值到另一个变量中,并没有作为对象的属性被调用,this指向window,例如:var func=obj.fax; func();

    3.函数用call或apply调用

    当一个函数被call或apply调用时,this指向传入的对象,例如:var  obj={name:'wewe',code:'dasda'}; var func=function (){console.log(this)};   func.call(obj);

    4.全局&调用普通函数

    在全局环境下,this永远指向window。普通函数在调用时,this也指向window,例如:var func=function(){console.log(this)};func();

下面例子中的情况需要注意:

    var  obj={

        name:'sddsd',

        func:function(){

                    function f(){

                        console(this);//这里this依然指向window

                    }

                    f();

                }    

    };

    obj.func();

关于this的补充内容

    在函数的原型链中,this代表的是当前函数对象的值,例如:function Func(){this.name='name';};  var func=new Func();   Func.prototype.getName=function (){console.log(this.name)};     func.getName();

作用域

    javascript中除了全局作用域,只有函数可以创建作用域,因此,在声明变量时,全局代码要在代码前端声明,函数中要在函数体一开始就声明好,且建议用单‘var’的形式声明变量。

    作用域有上下级的关系,上下级关系的确定是看函数是在哪个作用域下创建的。而作用域最大的好处就是隔离变量,不同作用域下的同名变量不会有冲突。作用域是在函数定义时就已经确定了,而不是在函数调用时。

    作用域是一个抽象的概念,类似于地盘,其中没有变量。要通过作用域对应的执行上下文来获取变量的值。作用域中变量的值是在执行过程中产生并确定的,而作用域则是在函数创建时确定的。如果要查找一个作用域下某个变量的值,需要到该作用域对应的执行上下文环境中寻找。

    自由变量需要到创建(非调用)该函数的那个作用域中取,这就是所谓的静态作用域。

    作用域链中取自由变量值的过程:

    1.在当前作用域下查找,有责获取并结束,无则下一步;

    2.若当前作用域为全局作用域,则证明该自由变量未定义,结束;否则继续;

    3.将创建该函数的作用域作为当前作用域;

    4.跳转到第一步;

 

使用闭包会增加内容开销(因为自由变量的存在,可能会导致一些存放自由变量的上下文环境无法及时销毁)

转载于:https://my.oschina.net/u/3992644/blog/2353503

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
闭包是指在一个函数内部定义的函数可以访问外部函数的变量和参数,即使外部函数已经执行结束。闭包形成一个封闭的作用域,保留了外部函数的变量和环境。这种特性使得闭包可以解决诸如变量私有化、保存变量状态等问题。 闭包的应用场景有很多,例如在异步编程中,可以使用闭包来保持状态,避免变量提升导致的错误;在模块化开发中,可以使用闭包来实现私有变量和方法的封装。但闭包也有一些注意事项,比如会占用内存,造成内存泄漏;还可能导致变量无法被垃圾回收,影响性能。 原型链是JavaScript中实现继承的机制。每个JavaScript对象都有一个内置的属性__proto__指向它的原型对象,原型对象又有自己的__proto__,形成了原型链。当访问对象的属性或方法时,会先在对象本身查找,如果找不到则沿着原型链向上查找,直到找到或者到达原型链的末尾(即null)。 原型链的好处是可以节省内存,将公共的属性和方法定义在原型对象中,所有实例对象共享这些属性和方法;还可以实现继承,子类对象的原型对象可以指向父类对象,从而共享父类的属性和方法。 原型链的缺点是只能继承父类的实例属性和方法,不能继承构造函数中的私有属性和方法;还有可能出现多个子类实例共享同一个父类实例的情况,导致数据共享的问题。 为了解决原型链继承的缺点,ES6引入了class关键字,可以更方便地实现面向对象编程,并且支持super关键字调用父类的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值