前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >js 函数作用域与this 的指向实例 原

js 函数作用域与this 的指向实例 原

作者头像
tianyawhl
发布2019-04-04 16:38:40
7650
发布2019-04-04 16:38:40
举报
文章被收录于专栏:前端之攻略

函数的定义分为2种,(1)直接定义-window 下,内部定义;(2)对象的方法(或对象原型的方法),下面的函数fn1与fn2 是直接定义的函数, doFunction是对象定义的方法,这2种情况使用name时 name来自相应的域

代码语言:javascript
复制
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;
    };
}


window.onload = function() {
    resultCon = document.getElementById('result');
    //定义了局部的name变量跟全局的var name = "window 下的name <br/ >";是两个不同的变量,也就是说这个局部的name变量不会覆盖全局的变量,如果去掉var则会覆盖全局name变量的值
    var name = "onload下的name<br/>";
    var fn2 = function() {
        resultCon.innerHTML += name;
    };
    fn1();//输出window下的name,窗口加载完定义些变量后执行fn1,此时fn1里面的name是全局的
    fn2();//onload下的name,由于定义了name在onload下的局部变量
    var obj = new MyObj();
    obj.doFunction();//MyObj下的name ,实例化构造函数,在函数内部重新定义了name,所有会显示MyObj下的name
};
代码输出结果:
window下的name
onload下的name
MyObj下的name

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

代码语言:javascript
复制
var name = 'window下的name<br/>';
var resultCon;
function fn1() {
    resultCon.innerHTML += this.name;//直接定义的函数this指向window
}

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


window.onload = function() {
    resultCon = document.getElementById('result');
    var name = "onload下的name<br/>";
    var fn2 = function() {
        resultCon.innerHTML += this.name;// 直接定义的函数this指向window
    };
    fn1();//window下的name
    fn2();//window下的name
    var obj = new MyObj();
    obj.doFunction();//MyObj下的name
};
代码输出结果:
window下的name
window下的name
MyObj下的name

JS容易犯错的this和作用域

代码语言:javascript
复制
var someuser = { 
    name: 'byvoid', 
    func: function() {
        console.log(this.name); 
    }
}; 
var foo = { 
    name: 'foobar'
};
 
someuser.func(); // 输出 byvoid
 
foo.func = someuser.func; 
foo.func(); // 输出 foobar
 
name = 'global';
func = someuser.func; 
func(); // 输出 global

上面的解释:上面定义了2个对象someuser 与foo 以及一个全局变量name = 'global';一个对象的方法可以赋给另一个对象的方法,但是一个对象的属性值不会赋给另一个对象所有foo.func(); // 输出 foobar
代码语言:javascript
复制
var scope = 'top';
var f1 = function() { 
    console.log(scope);
};
f1(); // 输出 top
var f2 = function() { 
    var scope = 'f2'; 
    f1();
};
f2(); // 输出 top
上面解释:静态作用域的含义是函数作用域的嵌套关系由定义时决定而不是调用时决定,又称为词法作用域,函数f1在查找变量定义时,在语法分析时就已经完成,而不需要等到f1被调用的时候才开始
上面的例子如果增加var scope = 'top1';则f2(); // 输出 top1,因为f2()调用前就已经确定好语法分析scope = 'top1' 如下
var scope = 'top';
var f1 = function() { 
    console.log(scope);
};
f1(); // 输出 top
var scope = 'top1';
var f2 = function() { 
    var scope = 'f2'; 
    f1();
};
f2(); // 输出 top1
代码语言:javascript
复制
<script>
var scope="global";  
function t(){  
    console.log(scope);  //undefined 
    var scope="local"  
    console.log(scope);  //local 
}  
t();  
</script>

但是当去掉后面的 var scope="local" console.log(scope);惊奇的事情发生了
<script>
var a = "global";
function myFunction() {
	 console.log(a);  //global
} 
 myFunction();
</script>

//原因是由于变量提升拆解为下面的就好理解了
    function t() {
        var scope;
        console.log(scope);
        scope = "local";
        console.log(scope);
    }
    t()
代码语言:javascript
复制
var name="global";    
if(true){    
    var name="local";    
    console.log(name)    
}    
console.log(name);  

全部输出local因为if没有作用域,所以在if里面的var定义是重新定义了一个全局变量将前面的全局变量覆盖了
代码语言:javascript
复制
<script>
name="lwy";  
function t(){  
    var name="tlwy";  
    function s(){  
        var name="slwy";  
        console.log(name);  
    }  
    function ss(){  
        console.log(name);  
    }  
    s();  //slwy
    ss(); // tlwy
}  
t();   
</script> 
当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。
然后从链表开头寻找变量name,很明显
name是"slwy"。
但执行ss()时,作用域链是: ss()->t()->window,所以name是”tlwy" 
代码语言:javascript
复制
var myvar = "my value";

(function() {
  console.log(myvar); // undefined  因为下面重新定义了局部变量,并且会变量提升, 相当于在console.log(myvar) 之前var myvar 如下:
  var myvar = "local value";
})();

var myvar = "my value";
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();


var myvar = "my value";
(function() {
  console.log(myvar); // my value  
  
})();

为创建的数组赋值 

代码语言:javascript
复制
function map() {
var a =	[0, 1, 2, 5, 10];  
 var result = []; // 创建一个新的数组
 var i;
  for (i = 0; i < a.length; i++)
    //var result = []; 不能放在此位置,因为每次循环时候result 都赋值为空
    result[i] = a[i]+2;
	alert(result);
	console.log(result);// 数组2,3,4,7,12
  return result;

}
代码语言:javascript
复制
function outside(x) {
  function inside(y) {
    return x + y;
  }
  return inside;
}

fn_inside = outside(3); 
result = fn_inside(5); 
console.log(result ) //8

arguments的用法 

代码语言:javascript
复制
function myConcat(separator) {
   var result = "", // initialize list
       i;
   // iterate through arguments
   for (i = 1; i < arguments.length; i++) {
      result += arguments[i] + separator;
      console.log(separator;)
//separator 接受的是第一个参数,(separator,separator1)若这样接受2个参数,separator形参接受的实参就是第一个参数,
   }
   return result;
}
你可以给这个函数传递任意数量的参数,它会将各个参数连接成一个字符串“列表”:

// returns "red, orange, blue, "
myConcat(", ", "red", "orange", "blue");
代码语言:javascript
复制
    var a = 20;
    var b = a;
    b = 30;
    console.log(a); //20
    var m = { a: 10, b: 20 };
    var n = m;
    n.a = 15;
    console.log(m.a); //15  对象是按引用访问的
代码语言:javascript
复制
var a = 20;
var obj = {
    a: 10,
    c: this.a + 20,
    fn: function() {
        return this.a
    }
}
console.log(obj.c); //40  由于c是属性不是方法,此时this指向window
console.log(obj.fn()); //10
var anotherobj = obj.fn;
console.log(anotherobj()); //20

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016/08/25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档