您的位置:首页 > Web前端 > JavaScript

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

2016-08-25 00:00 363 查看
摘要: 查看网上很多资料,整理

函数的定义分为2种,(1)直接定义-window 下,内部定义;(2)对象的方法(或对象原型的方法),下面的函数fn1与fn2 是直接定义的函数,
doFunction是对象定义的方法,这2种情况使用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;
};
}

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

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

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;// 对象的方法,this指向实例化对象,由于var obj = new MyObj();并没有实参,所以会显示undefined
};
}

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();//undefined
};
代码输出结果:
window下的name
window下的name
undefined

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(); // 输出 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

<script>
var scope="global";
function t(){
console.log(scope);  //undefined
local
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>

var name="global";
if(true){
var name="local";
console.log(name)
}
console.log(name);

全部输出local因为if没有作用域,所以在if里面的var定义是重新定义了一个全局变量将前面的全局变量覆盖了

<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"

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);//20  this的指向是在函数被调用时确定的,c不是函数
console.log(obj.fn());//10
var anotherobj=obj.fn;
console.log(anotherobj());//20
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: