网站常见问题是什么,济南搜到网络推广公司,营销网站建设哪里好薇,电脑版4399游戏网页this、闭包与作用域
this指针详解 函数的this关键字在JavaScript中的表现略有不同#xff0c;此外#xff0c;在严格模式和非严格模式之间也会有一些差别。在绝大多数情况下#xff0c;函数的调用方式决定了this的值(运行时绑定)。
this关键字是函数运行时自动生成的一个内…this、闭包与作用域
this指针详解 函数的this关键字在JavaScript中的表现略有不同此外在严格模式和非严格模式之间也会有一些差别。在绝大多数情况下函数的调用方式决定了this的值(运行时绑定)。
this关键字是函数运行时自动生成的一个内部对象只能在函数内部使用总指向调用它的对象。在函数执行过程中this一旦被确定了就不可以再更改。 JavaScript中this不是固定不变的它会随着执行环境的改变而改变。
全局上下文在全局作用域(也就是不在任何函数内部)中this指向全局对象。在浏览器环境中这个全局对象是window。函数被直接调用函数被直接调用(即不是作为对象的方法或不是通过new关键字)时this指向全局对象。对象的方法函数作为对象的方法被调用时this指向调用该方法的对象。构造函数函数通过new关键字被调用时(作为一个构造函数)this指向一个新创建的对象实例。箭头函数箭头函数不绑定自己的this它继承自包围它的函数或全局作用域的this。箭头函数中this指向不会改变用apply等等都不行。函数体内的this对象就是定义时所在的对象而不是使用时所在的对象。类似 call() 和 apply() 方法可以将 this 引用到任何对象。
作用域详解 作用域即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合。换句话说作用域决定了代码区块中变量和其他资源的可见性。一般将作用域分成全局作用域、函数作用域、块级作用域。 可以理解为是一个对象包含了当前执行环境的信息。当查找变量的时候会先从当前作用域对象中查找如果没有找到就会去父级查找一直找到全局对象window这样有多个执行上下文的变量对象构成的链条就叫做作用域链。作用域链的变量只能向上访问变量访问到window对象即被终止。 在js中包含三种作用域全局作用域/函数作用域/块级作用域。
全局作用域 任何不在函数中或是大括号中声明的变量都是在全局作用域下全局作用域下声明的变量可以在程序的任意位置访问。
函数作用域 函数作用域也叫局部作用域如果一个变量是在函数内部声明的它就在一个函数作用域下面。这些变量只能在函数内部访问不能在函数以外去访问。
块级作用域 ES6引入了let和const关键字和var关键字不同在大括号中使用let和const声明的变量存在于块级作用域中。在大括号之外不能访问这些变量。
默认绑定、显式绑定、隐式绑定 根据不同使用场合this有不同的值主要分为下面几种情况默认绑定、显式绑定、隐式绑定、new绑定。
默认绑定
如果在全局作用域(或称为函数外部)调用函数this指向全局对象。在浏览器中是window对象(在非严格模式下)在严格模式下是undefined。 在严格模式下(代码文件顶部使用use strict;)this会是undefined不能将全局对象用于默认绑定this会绑定到undefined。只有函数运行在非严格模式下默认绑定才能绑定到全局对象。如果函数被当作普通函数调用(即不是作为一个对象的方法或不是通过new关键字)this也指向全局对象。
显式绑定
使用call、apply或bind方法可以直接设置函数执行时this的值。call和apply会立即执行函数并接受一个对象作为this的值同时还可以传递参数列表。bind会创建一个新的函数当这个新函数被调用时this的值会被设置为bind的第一个参数并且它也可以接受额外的参数传递给原函数。
隐式绑定
当函数作为某个对象的方法被调用时this会被隐式地绑定到那个对象上。这时this就指这个上级对象就算一个函数是被最外层的对象所调用this指向的也只是它上一级的对象this永远指向的是最后调用它的对象。如果函数不是通过对象来调用即使它在对象内部定义this也不会绑定到那个对象上。如果函数是在一个对象的方法内部被调用并且这个函数是作为普通函数调用(而不是作为对象的方法调用)那么this可能并不会绑定到你所期望的对象上。为了避免这种情况可以使用call或apply来显式地设置this的值或者使用箭头函数来自动绑定this。
new 绑定
当使用new关键字来调用函数时会创建一个新的空对象并将this绑定到这个新创建的对象上。如果函数没有显式地返回一个非原始值(如对象或函数)new表达式的结果就是这个新创建的对象。注意null虽然也是对象但是return null的时候new仍然指向实例对象
闭包的概念 一个函数和对其周围状态(词法环境)的引用捆绑在一起(或者说函数被引用包围)这样的组合就是闭包。也就是说闭包让你可以在一个内层函数中访问到其外层函数的作用域。在JavaScript中每当创建一个函数闭包就会在函数创建的同时被创建出来作为函数内部与外部连接起来的一座桥梁。
function init() {var name Mozilla; // name 是一个被 init 创建的局部变量function displayName() { // displayName() 是内部函数一个闭包alert(name); // 使用了父函数中声明的变量}displayName();
}
init(); //displayName()没有自己的局部变量,由于闭包的特性它可以访问到外部函数的变量 闭包就是有权访问另一个函数作用域中的变量的函数创建闭包的最常见的方式就是在一个函数内创建另一个函数并将函数返回。
存储空间、执行上下文
存储空间 在JavaScript中存储空间通常指内存中的区域用于存储变量、函数、对象等。JavaScript引擎(如V8、SpiderMonkey等)管理着这部分内存并且会自动进行垃圾回收以释放不再使用的内存空间。 存储空间可以大致分为以下几类
堆内存用于存储对象实例和闭包等。堆内存是由JavaScript引擎自动管理的当不再需要某个对象时垃圾回收器会将其释放。
栈内存用于存储基本数据类型(如数字、字符串、布尔值)、函数调用的参数和局部变量等。栈内存是自动分配的并且遵循后进先出(LIFO)的原则。
代码段存储JavaScript代码本身。代码段是只读的防止程序意外地修改了它的指令。
执行上下文 执行上下文是JavaScript引擎在执行代码时创建的一个环境它定义了变量和函数的可访问性。每当JavaScript引擎开始执行一段代码(全局代码、函数代码或eval代码)时它都会创建一个新的执行上下文并将其推入执行上下文栈。
执行上下文的类型分为三种
全局执行上下文只有一个浏览器中的全局对象就是window对象this指向这个全局对象。当脚本开始执行时创建它包含了全局作用域中定义的变量和函数。全局执行上下文始终存在并且在整个脚本执行期间都保持活动状态。函数执行上下文存在无数个只有在函数被调用的时候才会被创建每次调用函数都会创建一个新的执行上下文。每当一个函数被调用时JavaScript引擎都会为其创建一个新的函数执行上下文。函数执行上下文包含了函数内部的局部变量、参数、以及函数的内部作用域链。Eval函数执行上下文指的是运行在eval函数中的代码很少用而且不建议使用。当使用eval()函数执行代码时也会创建一个新的执行上下文。不过由于eval()函数的安全风险和性能问题现代JavaScript开发中很少使用它。 只有全局上下文(的变量)能被其他任何上下文访问。可以有任意多个函数上下文每次调用函数创建一个新的上下文会创建一个私有作用域函数内部声明的任何变量都不能在当前函数作用域外部直接访问。 执行上下文栈是JavaScript引擎用于管理执行上下文的数据结构。当一个新的执行上下文被创建时它会被推入执行上下文栈的顶部。当当前执行上下文执行完毕后(例如函数执行完成或遇到return语句)它会被从执行上下文栈中弹出控制权返回到前一个执行上下文。
闭包的使用场景 任何闭包的使用场景都离不开这两点
创建私有变量和方法延长变量的生命周期 一般函数的词法环境在函数返回后就被销毁但是闭包会保存对创建时所在词法环境的引用即便创建时所在的执行上下文被销毁但创建时所在词法环境依然存在以达到延长变量的生命周期的目的。 闭包的优点是可以避免全局变量的污染缺点是闭包会常驻内存会增大内存使用量使用不当很容易造成内存泄露。
function makeSizer(size) { //例子在页面上添加一些可以调整字号的按钮return function() {document.body.style.fontSize size px;};
}
var size12 makeSizer(12);
var size14 makeSizer(14);
var size16 makeSizer(16);
document.getElementById(size-12).onclick size12;
document.getElementById(size-14).onclick size14;
document.getElementById(size-16).onclick size16;
柯里化函数 目的在于避免频繁调用具有相同参数函数的同时又能够轻松的重用。 指的是将一个多参数的函数拆分成一系列函数每个拆分后的函数都只接受一个参数。将多参数的函数转换成单参数的形式。
使用闭包模拟私有方法 在JavaScript中没有支持声明私有变量但我们可以使用闭包来模拟私有方法。
其他 例如计数器、延迟调用、回调等闭包的应用其核心思想还是创建私有变量和延长变量的生命周期。