作用域、原型链、闭包等概念理解

1、执行环境及作用域

(1).执行环境:

定义了变量或函数有权访问的其它数据,决定了它们的各自行为。每个执行环境都有一个与之关联的变量对象(variable object, VO),执行环境中定义的所有变量和函数都会保存在这个对象中,解析器在处理数据的时候就会访问这个内部对象。

全局执行环境是最外层的一个执行环境,在web浏览器中全局执行环境是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。每个函数都有自己的执行环境,当执行流进入一个函数的时候,函数的环境会被推入一个函数栈中,而在函数执行完毕后执行环境出栈并被销毁,保存在其中的所有变量和函数定义随之销毁,控制权返回到之前的执行环境中,全局的执行环境在应用程序退出(浏览器关闭)才会被销毁。

(2).作用域:

作用域就是变量和函数的可访问范围,控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域。

全局作用域:任何地方都可以定义拥有全局作用域的变量。

a.没有用var声明的变量(除去函数的参数)都具有全局作用域,成为全局   变量,所以声明局部变量必须要用var。

b.window的所有属性都具有全局作用域

c.最外层函数体外声明的变量也具有全局作用域

局部作用域:局部变量的优先级高于全局变量。

a.函数体内用var声明的变量具有局部作用域,成为局部变量

b.函数的参数也具有局部作用域

JavaScript是函数作用域(function scope),没有块级作用域。无论函数体内的变量在什么地方声明,对整个函数都是可见的,即JavaScript函数里声明的所有变量都被提前到函数体的顶部,只是提前变量声明,变量的赋值还是保留在原位置

(3).作用域链:

JavaScript的变量都是对象的属性,而该对象可能又是其它对象的属性,而所有的对象都是全局对象的属性,所以这些对象的关系可以看作是一条链,由于每个对象都有一个作用域,所以形成了一个作用域链。链头就是变量所处的对象,链尾就是全局对象。

当代码在一个环境中执行时,会创建变量对象的一个作用域链来保证对执行环境有权访问的变量和函数的有序访问。

2、原型链、继承

(1)理解原型对象

1).只要创建了一个新函数,就会为该函数创建一个prototype属性,这个属性指向函数的原型对象;

2).所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针;

3).当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。

(2)原型链

综上所述,假如我们让原型对象等于另一个类型的实例,则此时的原型对象将包含一个指向另一个原型的实例,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条,这就是原型链。

【注】:所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Object.prototype。这也正是所有自定义类型都会继承toString(),valueOf()等默认方法的根本原因。

(3)继承

1).通过原型链实现。不能使用对象字面量创建原型方法,因为这样会重写原型链。

缺点:最主要的问题是包含引用类型值的原型;二是在创建子类型的实例时,不能向超类型的构造函数中传递参数。

2)借用构造函数。在子类型构造函数的内部调用超类型构造函数。使用apply()和call()方法,可以向超类型的构造函数中传递参数。apply()和call()的作用一样,只是专递的参数形式不同,apply()的参数是以数组的形式传递,call()中是展开的形式。

缺点:函数复用无从谈起,而且在超类型的原型中定义的方法,对子类型而言是不可见的。

3).组合继承(原型链+借用构造函数)。避免了1)、2)的缺陷,融合了他们的优点,成为javascript最常用的继承模式,而且,instanceof和isPrototypeOf()也能够用于识别基于组合继承创建的对象。

3、闭包

(1).概念:有权访问另一个函数作用域中的变量的函数。简单理解为“定义在一个函数内部的函数”。

(2).好处:保护函数内的变量安全,加强了封装性;在内存中维持一个变量(缓存);匿名自执行函数;模拟面向对象编程。

(3).应用场景:使用闭包代替全局变量;函数外或在其他函数中访问某一函数内部的参数;包装相关功能;为节点循环绑定click事件,在事件函数中使用当次循环的值或节点,而不是最后一次循环的值或节点;

(4).缺点:常驻内存,会增大内存使用量,使用不当很容易造成内存泄露,更重要的是,对闭包的使用不当会造成无效内存的产生。

时间: 2024-12-19 10:26:20

作用域、原型链、闭包等概念理解的相关文章

对js原型链及继承的理解:__proto__&prototpye

首先我们来理解一下原型链的概念: 要理解原型链必须知道构造函数.原型和实例的关系: 每个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针(即prototype),而实例则包含一个指向原型对象的内部指针(即__proto__). var father = function() { this.relation = "father"; } father.prototype.money = function() { this.money = 100000; } var father

对Javascript 类、原型链、继承的理解

一.序言 ??和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承.(以下不讨论ES6中利用class.extends关键字来实现类和继承:实质上,ES6中的class.extends关键字是利用语法糖实现的) Javascript灵活到甚至可以实现接口的封装(类似Java中的Interface和implements). 二.类的实现 1.我对类的理解 ??首先,

JS高级(三)--原型链、闭包、作用域、函数的四种调用方式

一.原型链(家族族谱) 概念:JS里面的对象可能会有父对象,父对象还会有父对象,.....祖先 根本:继承 属性:对象中几乎都会有一个__proto__属性,指向他的父对象 意义:可以实现让该对象访问到父对象中相关属性 根对象:Object.prototype var arr=[1,3,5] arr.__proto__:Array.prototype arr.__proto__.__proto__就是找到了根对象 function Animal(){} var cat=new Animal();

深入理解JS原型链与继承

我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天要讨论的主题,有许多人写过许多精彩的文章,但是今天我还是想把自己的理解的知识记录下来.我在学习 掌握JS原型链和继承的时候,就是看得@阮一峰老师的写的文章,觉得他写的技术类的文章都容易让理解,简明概要,又好理解.他是我学习JS路程里面一个比较佩服的导师,昨天重新看了他写的<Javascript 面向

《JavaScript 闯关记》之原型及原型链

原型链是一种机制,指的是 JavaScript 每个对象都有一个内置的 __proto__ 属性指向创建它的构造函数的 prototype(原型)属性.原型链的作用是为了实现对象的继承,要理解原型链,需要先从函数对象.constructor.new.prototype.__proto__ 这五个概念入手. 函数对象 前面讲过,在 JavaScript 里,函数即对象,程序可以随意操控它们.比如,可以把函数赋值给变量,或者作为参数传递给其他函数,也可以给它们设置属性,甚至调用它们的方法.下面示例代

Angularjs Scope 原型链

我们知道scope是可以继承的.scope的继承和js原型链是同一个概念. <div ng-controller="parentCtrl"> {{name}} <div ng-controller="childCtrl"> {{name}} </div> </div> 在angular中,ng-controller指令会帮我们创建一个scope并继承它的父亲scope . parentCtrl scope继承自 $ro

JavaScript(2)——对象属性、原型与原型链

对象属性.原型与原型链 哈哈哈,我的第二篇博客哟,说的是对象属性.原型与原型链.可能这些只是某些小点串联起来的,逻辑性没有很强.所以会对文章的可读性和理解性带来一些困扰.不过,今天我又前进了那么一小步,为之后的学习又打下了那么一丢丢的基础,虽然理解的不是特别好,不过我还会理解第二次,第三次.恩.加油! [对象] 对象中包含一系列的属性.这些属性都是无序的,每个属性都有一个字符串key和对应的value. 创建自定义对象的最简单方式就是创建一个object实例,然后再为它添加属性和方法. 属性类型

JavaScript之继承(原型链)

我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法.JavaScript不支持签名,因此只有实现继承.其中实现继承主要是依赖于原型链的.下面我将以原型链为重点说说继承的几种主要的方式: 原型链继承 借用构造函数继承 组合继承(重点) 第一部分:原型链继承 A 要说原型链继承,不得不首先介绍一下原型链的概念. 想象一下,如果使原型对象等于另一个对象的实例,则此时原型对象将包含一个指向另一

javascript 原型链

一.什么是原型链 当需要获取一个对象的某个属性或方法时,首先在对象自身查找该属性,找不到的话,会沿着原型链向上查找,直到在某个原型中找到该属性,如果到达原型链顶端依然找不到,则返回undefined. 1 var person = {name : "Peter"}; 2 3 //Peter 4 console.log(person.name); 5 6 //undefined 7 console.log(person.age); 8 9 Object.prototype.age = 1