深入理解js函数的作用域与this指向

函数的作用域与this指向是js中很重要的一部分,理清这点东西需要个逻辑,看看我的逻辑怎么样...

下面是个提纲,可以直接挑你感兴趣的条目阅读。

• 函数的定义方式:直接定义(window下,内部定义),对象的方法,对象原型的方法;

• 函数的调用方式:直接调用,call/apply,with

• 对于直接定义的函数和对象的方法,作用域默认状态下是它的定义处的作用域链。

• 对于直接定义的函数,this指向window。

• 对于对象的方法,this指向实例化对象(对应于实例化对象默认返回this的情况)。

• 用call/apply改变方法的this指向

• 在函数或方法的定义时可以通过with改变其作用域链。

下面分开来具体说说:

函数的定义,如提纲中提到的可以分为两种:直接定义(window下,内部定义),对象的方法(或对象原型的方法)。从下面的示例代码中可以看到函数fn1与fn2以及对象的方法doFunction在函数使用name时name的值来自相应的域。

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
  resultCon.innerHTML += name;
}

function MyObj() {
  var name = 'MyObj下的name<br/>';
  this.doFunction = function() {
    resultCon.innerHTML += name;

在使用name的值时将“name”用“this.name”来代替会出现什么情况呢,看下例:

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
  resultCon.innerHTML += this.name;
}

function MyObj() {
  var name = 'MyObj下的name<br/>';
  this.doFunction = function() {
    resultCon.innerHTML += this.name;

从结果来看可以验证提纲中的第4和5条,也可以看到this和作用域是两套分离的链,遵循个自的变量查询逻辑,具体的查询逻辑在下面的性能分析中会提到,如果是新手建议先看一下“js的作用域链”方面的基础知识。

关于函数的调用方法,我用下面的方示例说明提纲中的第2、6条:

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
  resultCon.innerHTML += this.name;
}

function MyObj() {
  var name = 'MyObj下的name<br/>';
  this.doFunction = function() {
    resultCon.innerHTML += this.name;

调用时call和apply的使用是为了改变被调用函数的this指向。with的使用是为了改变被调用函数中变量的查询域。我们把上例中的call和name前的this去掉再加上with来演示with的作用。

var name = 'window下的name<br/>';
var resultCon;
function fn1(myScope) {
  with (myScope) {
    resultCon.innerHTML += name;
  }
}

function MyObj(myScope) {
  var name = 'MyObj下的name<br/>';

看到with的使用并不方便,需要在被调用函数中添加with,有人可能想能不能向下面那样调用来整体改变变量作用域而不去改变被调用函数呢?

with (myScope) {
  fn1();
  fn2();
  var obj = new MyObj();
  obj.doFunction();
}

很遗憾,不可以!所以在一些成熟的框架中随处可见call和apply的使用,却很少用到with,在用JSHint检测js语法的时候with处都标了小红点,在一些js编码指导中也建议尽量少用with,因为with改变了变量的默认查询链,所以会给后期的维护人员一些困惑,还有性能方面的一些考虑,请慎用with。

以上这篇深入理解js函数的作用域与this指向就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

时间: 2016-05-27

聊一聊JS中this的指向问题

JS中的this指向一直是个让人头疼的问题,想当初我学的是天昏地暗,查了好多资料,看的头都大了,跟他大战了那么多回合,终于把它搞定个七八分,其实往往都是我们复杂化了,现在就让大家轻松看懂this的指向,我会分以下几种情况来说. this的指向: 1.this 指的是调用当前方法(函数)的那个对象,也就是说函数在谁那被调用,this就指的是谁. 来看两个栗子: oBtn.onclick = function(){ alert(this); //oBtn } oBtn[i].onclick = fn

理解javascript中的严格模式

一.什么是严格模式 我们平时写的JavaScript代码一般都运行在正常模式中的,除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode).看名字就知道,这种模式会让JavaScript在更严格的环境中运行. 包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱.(github上面好多项目都是用的严格模式) 二.启用严格模式 为整个脚本启用严格模式 在所有语句之前放一个特定语句 "use strict"

JavaScript严格模式下关于this的几种指向详解

前言 相信不少人在学习或者使用Javascript的时候,都曾经被 JavaScript 中的 this 弄晕了,那么本文就来整理总结一下在严格模式下 this 的几种指向. 一.全局作用域中的this 在严格模式下,在全局作用域中,this指向window对象 "use strict"; console.log("严格模式"); console.log("在全局作用域中的this"); console.log("this.docume

老生常谈 js中this的指向

在js中this的指向对于新手来说一定是个难题,但是如果你真正理解了的话,也就没什么问题啦,下面就来讲讲this吧. JS中,this的值取决于调用的模式(调用对象),而JS中共有4种调用模式: 1.函数调用模式 当一个函数不是一个对象的属性时,当作函数俩调用,这时函数内的this指向全局对象(大对数情况下是window) window.value=1; function getValue(){ console.log(this.value); } getValue();//输出1,此时的thi

js严格模式总结(分享)

首页,我们要理解严格模式的概念,严格模式是一种特殊的执行模式,它修复了部分语言上的不足,提供更强的错误检查,病增强安全性.可以对部分函数进行执行严格模式,如: function func(){ 'use strict' } 也可以对整个js文件进行执行严格模式,如: 'use strict' function func(){ } 那么我们在以下情况不能使用: 1.不允许用width 2.不允许未声明的变量被赋值 3.arguments变为参数的静态副本 4.delete参数.函数名报错 5.de

JavaScript起点(严格模式深度了解)

严格模式(Strict Mode)是ECMAScript5新增的功能.ECMAScript5虽然可以向后兼容ECMAScript3,但如果使用严格模式,哪些ECMAScript5"不在建议使用"的ECMAScript3语法功能将会被全部进制,如果出现就会抛出一行.引入Strict Mode目的是允许开发人员能够选择"更好"的Javascript版本,这个版本能用不同的方式处理那些普遍而又臭名昭著的错误.目前所有的主流浏览器的最新版本--包括IE10与Opera12-

Javascript的严格模式strict mode详细介绍

"严格模式"(strict mode)是ECMA-262 Edition 5定义的新语法,表示要用严格的Javascript语法来执行,有一些过去惯用的写法就会抛出SyntaxError异常,例如:1.变量前没有用var宣告2.使用八进制语法:var n = 023和var s = "\047"3.使用with语句4.使用delete删除一个变量名(而不是属性名):delete myVariable5.使用eval或arguments作为变量名或函数名6.使用未来保

灵活的理解JavaScript中的this指向

this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要.首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题.

全面理解JavaScript中的继承(必看)

JavaScript中我们可以借助原型实现继承. 例如 function baz(){ this.oo=""; } function foo(){ } foo.prototype=new baz(); var myFoo=new foo(); myFoo.oo; 这样我们就可以访问到baz里的属性oo啦.在实际使用中这个样不行滴,由于原型的共享特点(数据保存在了堆上), 所有实例都使用一个原型,一但baz的属性有引用类型就悲剧了,一个实例修改了其他实例也都跟着变了...wuwuwu 自

AJAX入门之深入理解JavaScript中的函数

概述 函数是进行模块化程序设计的基础,编写复杂的Ajax应用程序,必须对函数有更深入的了解.JavaScript中的函数不同于其他的语言,每个函数都是作为一个对象被维护和运行的.通过函数对象的性质,可以很方便的将一个函数赋值给一个变量或者将函数作为参数传递.在继续讲述之前,先看一下函数的使用语法: function func1(-){-}var func2=function(-){-};var func3=function func4(-){-};var func5=new Function()

深入理解Javascript中this的作用域

大家在使用Javascript的时候经常被this这个家伙搞得晕头转向的.对大多数有OOP开发经验的开发人员来说this是当前作用域中引用普通元素的标识符,但是在Javascript中它却显得古灵精怪的,因为它不是固定不变的,而是随着它的执行环境的改变而改变.在Javascript中this总是指向调用它所在方法的对象. 举一个简单的例子: 复制代码 代码如下: function test(){ alert(this); } var obj=function(){ var name='testO

探寻JavaScript中this指针指向

探寻JavaScript中this指针指向 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题. 为什么要学习this?如果你学过函数式编程,面向对象编程,那你肯定知

Javascript中this关键字指向问题的测试与详解

前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript可以通过一定的设计模式来实现面向对象的编程,其中this "指针"就是实现面向对象的一个很重要的特性.本文将给大家详细介绍关于Javascript中this关键字指向的相关内容,让我们先做一个小测试,如果全部答对了,恭喜你不用往下看了. 测试题目 第一题 <script> var str = 'zhangsan'; function

深入理解JavaScript中的call、apply、bind方法的区别

在JavaScript 中,this的指向是动态变化的,很可能在写程序的过程中,无意中破坏掉this的指向,所以我们需要一种可以把this的含义固定的技术,于是就有了call,apply 和bind这三个方法,来改变函数体内部 this 的指向,因为函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念 apply.call apply:应用某一对象的一个方法,用另一个对象替换当前对象 call:调用一个对象的一个方法,以另一个对象替换当前对象 function pers

详解JavaScript中关于this指向的4种情况

对很多前端开发者来说,JavaScript语言的this指向是一个令人头疼的问题.先看下面这道测试题,如果你能实现并解释原因,那本文对你来说价值不大,可以直接略过. **开篇测试题:**尝试实现注释部分的Javascript代码,可在其他任何地方添加更多代码(如不能实现,说明一下不能实现的原因): let Obj = function (msg) { this.msg = msg this.shout = function () { alert(this.msg) } this.waitAndS

深入理解JavaScript中的对象复制(Object Clone)

JavaScript中并没有直接提供对象复制(Object Clone)的方法.因此下面的代码中改变对象b的时候,也就改变了对象a. a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制. 用jQuery进行对象复制 在可以使用jQuery的情况下,jQuery自带的extend方法可以用来实现对象的复制. a = {k1:1, k2:2, k3:3}; b = {}; $.extend(b,a); 自定义clone

关于JavaScript中的this指向问题总结篇

在javascript中this的指向一直是前端同事的心头病,也同时是各面试题的首选,现在我们就来总结一下js中this的指向.首先需要了解一下几个概念: 1:全局变量默认挂载在window对象下 2:一般情况下this指向它的调用者 3:es6的箭头函数中,this指向创建者,并非调用者 4:通过call.apply.bind可以改改变this的指向 下面我们具体分析一下 1:在函数调用时 (非严格模式) const func = function () { console.log(this)