函数的定义分为2种,(1)直接定义-window 下,内部定义;(2)对象的方法(或对象原型的方法),下面的函数fn1与fn2 是直接定义的函数,
doFunction是对象定义的方法,这2种情况使用name时 name来自相应的域var name = 'window下的name';var resultCon;function fn1() { resultCon.innerHTML += name;}function MyObj() { var name = 'MyObj下的name'; this.doFunction = function() { resultCon.innerHTML += name; };}window.onload = function() { resultCon = document.getElementById('result'); //定义了局部的name变量跟全局的var name = "window 下的name ";是两个不同的变量,也就是说这个局部的name变量不会覆盖全局的变量,如果去掉var则会覆盖全局name变量的值 var name = "onload下的name"; 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下的nameonload下的nameMyObj下的name
对于直接定义的函数。this指向window
var name = 'window下的name';var resultCon;function fn1() { resultCon.innerHTML += this.name;//直接定义的函数this指向window}function MyObj() { this.name = 'MyObj下的name';//或者var name = 'MyObj下的name'; this.doFunction = function() { resultCon.innerHTML += this.name; };}window.onload = function() { resultCon = document.getElementById('result'); var name = "onload下的name"; var fn2 = function() { resultCon.innerHTML += this.name;// 直接定义的函数this指向window }; fn1();//window下的name fn2();//window下的name var obj = new MyObj(); obj.doFunction();//MyObj下的name};代码输出结果:window下的namewindow下的nameMyObj下的name
JS容易犯错的this和作用域
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
var scope = 'top';var f1 = function() { console.log(scope);};f1(); // 输出 topvar 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(); // 输出 topvar scope = 'top1';var f2 = function() { var scope = 'f2'; f1();};f2(); // 输出 top1
但是当去掉后面的 var scope="local" console.log(scope);惊奇的事情发生了//原因是由于变量提升拆解为下面的就好理解了 function t() { var scope; console.log(scope); scope = "local"; console.log(scope); } t()
var name="global"; if(true){ var name="local"; console.log(name) } console.log(name); 全部输出local因为if没有作用域,所以在if里面的var定义是重新定义了一个全局变量将前面的全局变量覆盖了
当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显name是"slwy"。但执行ss()时,作用域链是: ss()->t()->window,所以name是”tlwy"
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 })();
为创建的数组赋值
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;}
function outside(x) { function inside(y) { return x + y; } return inside;}fn_inside = outside(3); result = fn_inside(5); console.log(result ) //8
arguments的用法
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");
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 对象是按引用访问的
var a = 20;var obj = { a: 10, c: this.a + 20, fn: function() { return this.a }}console.log(obj.c); //40 由于c是属性不是方法,此时this指向windowconsole.log(obj.fn()); //10var anotherobj = obj.fn;console.log(anotherobj()); //20