• JavaScript概念总结:作用域、闭包、对象与原型链


    JavaScript变量作用域

    1.1 函数作用域

    没有块作用域:即作用域不是以{}包围的,其作用域完成由函数来决定,因而if /for等语句中的花括号不是独立的作用域。

    如前述,JS的在函数中定义的局部变量只对这个函数内部可见,称之谓函数作用域。

    嵌套作用域变量搜索规则:当在函数中引用一个变量时,JS会搜索当前函数作用域,如果没有找到则搜索其上层作用域,一直到全局作用域。

    [javascript] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. var  value = 'global';  
    2. var f1 = function(){  
    3.   console.log(v1);   //global  
    4. };  
    5. f1();  
    6. var f2 = function(){  
    7.   var v1 ='local';  
    8.   console.log(v1); //local  
    9. };  
    10. f2();  



    词法作用域规则:函数的嵌套关系是定义时决定的,而非调用时决定的,即词法作用域,即嵌套关系是由词法分析时确定的,而非运行时决定。

    [javascript] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. var v1 = 'global';  
    2. var f1 = function(){  
    3.   console.log(v1);    
    4. }  
    5. f1();  //global  
    6. var f2 = function(){  
    7.   var v1 = 'local';  
    8.   f1();  
    9. };  
    10. f2();  //global  



    对于这两个规则的相互作用,函数内无论什么位置定义的局部变量,在进入函数时都是已经定义的,但未初始化,即为undefined,直到运行到变量被赋值时才被初始化,因此若访问了未初始化的变量,我们会得到undefined的说明。

    [javascript] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. var v1 = 'global';  
    2. var f = function(){  
    3.   console.log(v1);   //undefined  
    4.   var v1 =  'local';  
    5. };  



    1.2 全局作用域

    全局作用域的变量是全局对象的属性,不论在什么函数中都可以直接访问,而不需要通过全局对象,但加上全局对象,可以提供搜索效率。

    满足下列条件的变量属于全局作用域:

    在最外层定义的变量

    全局对象的属性

    任何地方隐匿定义的变量。

    2 闭包

    2.1 装饰的定义

    [javascript] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. function f1(){  
    2.   //context define  
    3.   function f2(){  
    4.    //func define   
    5.  };  
    6.   return f2;  
    7. };  
    8. f2(); //获得f1中的context  



    在类似C/C++这种的非函数式编程语言中,我们也可以定义函数指针并返回,但外层函数在执行结束后为内层函数定义的上下文信息会被销毁,而在闭包中,则保存了返回的函数,还包含返回函数的上下文信息。(由词法作用域所支持)而且在返回闭包之后,上下文信息即被单独创建出来,从而可以生成多个互相独立的闭包实例。

    2.2 闭包的用途

    闭包有两个用途,一是方便实现嵌套的回调函数,二是隐藏对象的细节。

    对于前者,NodeJS的编程风格已经可以说明问题,对二后者,对于函数内部的局部变量外部是不可见的,但可以提供访问函数来访问和修改相应的局部变量,从而实现OO封装的意图。

    3 对象

    在基于类型的语言中,对象是由类实例化,而JS是基于原型的系统,对象是由原型复制生成的。

    3.1 对象的创建与访问

    JavaScript中的Object实际上就是一个由属性组成的关联数组,属性由名称和值组成。可以由new Object()或{}来创建对象。对于创建简单对象,可以使用对象初始化器来创建对象,即由{}字面值来创建对象,对象的属性名可以为加''的字符串,也可不加引号。这对JS来说没有区别,访问对象的属性时,可以使用句点也可使用关联数组['name'],后者的好处是当我们不知道对象属性名时,可以由变量来作为关联数组的索引。

    3.2 构造函数

    我们也可以通过自定义构造函数来生成对象,从而能实例化更多的对象。构造函数也是函数,我们需要用大写的函数名即可。在函数中可以定义成员变量,成员函数等。

    3.3 上下文对象

    在JS中,上下文对象即this指针,即被调用函数所处的环境。其作用是在函数内部引用到调用它的对象本身。this的出现会之前介绍的静态作用域产生影响,加入了动态的内容。

    由例子可以看到,我们可以通过不同的变量引用函数,不同之处调用上下文。

    传递与绑定上下文

    JavaScript的函数可以通过Call和Apply来动态绑定到特定的上下文。

    如果想永久的绑定上下文,可以使用bind函数,需要注意的是同一函数上的多次bind是没有效果的。

    [javascript] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. var person = {  
    2.   name:'noname',  
    3.    getName:function(){console.log(this.name); }  
    4. };  
    5.   
    6. var bill = {name:'Bill'};  
    7. person.getName(); //noname  
    8. bill.getName = person.getName;  
    9. bill.getName();         //Bill  
    10. name = 'JavaScript';  
    11. func = person.getName;  
    12. func();         //JavaScript  



    3.4 原型

    创建对象时,我们应该在构造函数内定义一般成员,而是其原型定义成员函数。

    下面我们会主要介绍原型链

    JS中有两个特殊的对象:Object与Function,它们都是构造函数,用于生成对象。

    Object.prototype是所有对象的祖先,Function.prototype是所有函数的原型,包括构造函数。

    可以将JS的对象分为三类:用户创建对象,构造函数对象,原型对象。

    所有对象中都有一个__proto__属性,其指向此对象的原型。

    构造函数对象有prototype,指向其原型对象,通过此构造函数创建对象时,新创建对象的__proto__属性将会指向构造函数的prototype属性。

    原型对象有一个constructor属性,指向它对应的构造函数。

    function Foo() {}
    var obj = new Object();
    var foo = new Foo();

    参考文献:《Node.js开发指南》

  • 相关阅读:
    关于Java常见的误解
    Java程序设计概述
    是结束,更是开始!
    从零开始单排学设计模式「简单工厂设计模式」黑铁 III
    某神秘公司 RESTful、共用接口、前后端分离、接口约定的实践
    这40张图送给单身程序员,情人节请一笑而过!
    科技圈晒开工福利!2019一起定个小目标!
    IDEA一定要懂的32条快捷键
    假期结束了,我相信未来会更好!
    有一种痛,叫 “今年没有年终奖”!!!
  • 原文地址:https://www.cnblogs.com/xiaofox0018/p/6364522.html
Copyright © 2020-2023  润新知