【问题标题】:function's local var not getting argument value函数的本地变量没有得到参数值
【发布时间】:2015-03-27 04:05:34
【问题描述】:

这对我来说似乎很奇怪。我有

var j = "x";
var k = "y";

function fun1 ( a, b) {
  var j = a;
  var k = b;
  console.log("this.j is:", this.j);
  console.log("this.k is:", this.k);
  this.j = a;
  this.k = b;
  return this.j + this.k;
};

console.log("j is ", j);
console.log("k is ", k);
console.log("fun1(3,4) is ", fun1(3,4));
console.log("j is ", j);
console.log("k is ", k);
console.log("fun1(2,7) is ", fun1(2,7));
console.log("j is ", j);
console.log("k is ", k);

当我在 Node.js 中运行它时,我得到:

j is  x
k is  y
this.j is: undefined
this.k is: undefined
fun1(3,4) is  7
j is  x
k is  y
this.j is: 3
this.k is: 4
fun1(2,7) is  9
j is  x
k is  y

为什么 j 和 k 在声明时不被设置为函数中的参数 a 和 b?我必须同时做 var j = a; 似乎是不对的。 AND this.j = a; !!我做错了什么?

在 node 中,输出正确显示 global 中的 j 和 k 变量没有被 fun1 中的局部变量 j 和 k 破坏。当我在 Chrome 或 Firefox 中运行它时,全局变量确实被破坏了。换句话说,我得到了

j is  x
k is  y
this.j is: undefined
this.k is: undefined
fun1(3,4) is  7
j is  3
k is  4
this.j is: 3
this.k is: 4
fun1(2,7) is  9
j is  2
k is  7

为什么局部范围不能保护全局变量?

感谢任何提示。

【问题讨论】:

  • 您正在设置局部变量 var j = a; 的值,当您使用 this.a 时,您正在尝试访问由 this 引用的对象的名为 a 的属性不同的价值观...
  • this 浏览器内部函数是window。全局只是意味着最外部范围的本地,在浏览器的情况下是window
  • 谢谢。 Doh - 是的,不应该使用 this,我只是覆盖了本地范围。

标签: javascript function scope arguments var


【解决方案1】:

我建议你去阅读! :) 这准确地解释了如何使用 this 以及 this 是什么! Read here! Mozilla Developper Network

如果链接失效,这里是文章。 (抱歉,格式不完善,文字很长。)

总结 函数的 this 关键字在 JavaScript 中的行为略有不同 与其他语言相比。它之间也有一些区别 严格模式和非严格模式。

在大多数情况下,this 的值取决于函数的运行方式 叫。执行时不能通过赋值来设置,可能是 每次调用函数时都不同。 ES5 引入了绑定 设置函数 this 值的方法,无论它如何 调用。

语法 this 全局上下文 在全局执行上下文中(外部 任何函数),this指的是全局对象,无论是严格的 模式与否。

console.log(this.document === 文档); // 是的

// 在网络浏览器中,window 对象也是全局对象: console.log(this === window); // 是的

this.a = 37;控制台.log(window.a); // 37 函数上下文 函数,this的值取决于函数的调用方式。

简单的调用

function f1(){   return this; }

f1() === window; // global object In this case, the value of this is

不是由调用设置的。由于代码不是在严格模式下,值 of this 必须始终是一个对象,因此它默认为全局对象。

function f2(){ "使用严格"; // 查看严格模式 return this; }

f2() === undefined; 

在严格模式下, this 的值保持在 进入执行上下文时设置的任何值。如果不是 已定义,它仍然未定义。它也可以设置为任何值,例如 为 null 或 42 或“我不是这个”。

注意:在第二个例子中,这应该是未定义的,因为 f2 是 在不提供任何基础的情况下调用(例如 window.f2())。此功能 一些浏览器刚开始支持时没有实现 严格模式。结果,他们错误地返回了窗口对象。 作为对象方法

当一个函数作为一个对象的方法被调用时,它的 this 被设置为 调用该方法的对象。

在以下示例中,当调用 o.f() 时,在函数内部 this 绑定到 o 对象。

var o = {   prop: 37,   f: function() {
    return this.prop;   } };

console.log(o.f()); // logs 37 Note that this behavior is not at all

受函数定义方式或位置的影响。在上一个 例如,我们将函数 inline 定义为 f 成员在 o的定义。然而,我们可以很容易地定义 首先是函数,然后将其附加到 o.f.这样做会导致 相同的行为:

var o = {prop: 37};

 function independent() {   return this.prop; }

o.f = independent;

console.log(o.f()); // logs 37 This demonstrates that it matters only

该函数是从 o 的 f 成员调用的。

同样,this 绑定只受最直接的 会员参考。在下面的示例中,当我们调用 函数,我们称它为对象 o.b 的方法 g。这次期间 执行时,函数内部的 this 将引用 o.b.事实是 对象本身是 o 的成员,没有结果;最多 立即参考是最重要的。

o.b = {g: independent, prop: 42}; console.log(o.b.g()); // logs 42
this on the object's prototype chain

同样的概念也适用于定义在 对象的原型链。如果方法在对象的原型上 链,this 指的是调用该方法的对象,就好像 方法在对象上。

var o = {f:function(){ return this.a + this.b; }}; var p =
Object.create(o); p.a = 1; p.b = 4;

console.log(p.f()); // 5 In this example, the object assigned to the

变量 p 没有自己的 f 属性,它从它的 原型。但最终查找 f 并不重要 在 o 上找到具有该名称的成员;查找开始作为参考 p.f,所以函数内部的 this 获取对象的值 简称p。也就是说,由于 f 被称为 p 的方法,所以它的 这是指p。这是 JavaScript 的一个有趣的特性 原型继承。

这个带有getter或setter

同样,当一个函数从一个 吸气剂或二传手。用作 getter 或 setter 的函数有它的 this 绑定到设置或获取属性的对象。

function modulus(){   return Math.sqrt(this.re * this.re + this.im *
this.im); }

var o = {   re: 1,   im: -1,   get phase(){
    return Math.atan2(this.im, this.re);   } };

Object.defineProperty(o, 'modulus', {
    get: modulus, enumerable:true, configurable:true});

console.log(o.phase, o.modulus); // logs -0.78 1.4142 As a constructor

当一个函数用作构造函数时(使用 new 关键字),它的 this 绑定到正在构造的新对象。

注意:虽然构造函数的默认值是返回对象 被 this 引用,它可以改为返回一些其他对象(如果 返回值不是对象,则返回this对象)。

/* * 构造函数的工作方式如下: * * function MyConstructor(){ * // 实际的函数体代码在这里。 * // 创建属性 |这个| as * // 通过分配给他们想要的。例如,* this.fum = “名义”; * // 等等... * * // 如果函数有返回值 * // 返回一个对象的语句,该对象将是 *
// |new| 的结果表达。否则,* // 的结果 表达式是对象 * // 当前绑定到 |this| * // (即最常见的情况)。 * } */

function C(){   this.a = 37; }

var o = new C(); console.log(o.a); // logs 37


function C2(){   this.a = 37;   return {a:38}; }

o = new C2(); console.log(o.a); // logs 38 In the last example (C2),

由于在构造过程中返回了一个对象,因此新对象 这注定会被丢弃。 (这基本上使 语句“this.a = 37;”死代码。它并没有完全死去,因为 它会被执行,但可以在没有外部影响的情况下消除它。)

致电申请

如果函数在其主体中使用 this 关键字,则其值可以是 使用调用或应用绑定到调用中的特定对象 所有函数都继承自 Function.prototype 的方法。

function add(c, d){   return this.a + this.b + c + d; }

var o = {a:1, b:3};

// 第一个参数是用作 // 'this' 的对象,后续 参数在函数调用中作为 // 参数传递 add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

// 第一个参数是用作 // 'this' 的对象,第二个 是一个数组,其 // 成员用作函数中的参数 调用 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 注意 调用并应用,如果作为 this 传递的值不是对象,则 将尝试使用内部将其转换为对象 ToObject 操作。因此,如果传递的值是像 7 或 'foo',它将使用相关的转换为对象 构造函数,因此原始数字 7 被转换为对象,就好像 通过 new Number(7) 和字符串 'foo' 到一个对象,就好像通过 new 字符串('foo'),例如

function bar() {   console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number] The bind method

ECMAScript 5 引入了 Function.prototype.bind。打电话 f.bind(someObject) 创建一个具有相同主体和范围的新函数 作为 f,但在原始函数中出现这种情况时,在新函数中 函数它永久绑定到 bind 的第一个参数, 不管函数是如何使用的。

function f(){   return this.a; }

var g = f.bind({a:"azerty"}); console.log(g()); // azerty

var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty As

DOM 事件处理程序

当一个函数用作事件处理程序时,它的 this 被设置为 触发事件的元素(某些浏览器不遵循此 使用其他方法动态添加的侦听器的约定 addEventListener)。

// 当作为监听器调用时,将相关元素变为蓝色函数 bluify(e){ // 始终为真 console.log(this === e.currentTarget);
// 当 currentTarget 和 target 是同一个对象时为真
console.log(this === e.target); this.style.backgroundColor = '#A5D9F3'; }

// Get a list of every element in the document var elements =
document.getElementsByTagName('*');

// Add bluify as a click listener so when the // element is clicked

打开,它变成蓝色 for(var i=0 ; i 元素[i].addEventListener('click', blueify, false); } 在一个在线 事件处理程序

当从内联处理程序调用代码时,它的 this 被设置为 放置监听器的 DOM 元素:

显示这个 上面的警报显示按钮。但请注意,只有 外部代码是这样设置的:

显示内部 this 在这种情况下,内部函数的 this 没有设置所以它 返回全局/窗口对象(即默认对象 非严格模式,这不是由调用设置的)。

【讨论】:

    猜你喜欢
    • 2018-02-15
    • 2010-12-20
    • 2019-09-07
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    相关资源
    最近更新 更多