<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
function CMyObj(){
var n = 0;
function hello(){
n++;
console.log('n:' + n);
}
this.print = function(){
console.log('n value is:' + n);
}
if ( CMyObj.prototype.add == undefined)
{
CMyObj.prototype.add = function(){
hello();
}
}
}
window.onload = function(){
document.getElementById('btn1').onclick = function(){
var m1 = new CMyObj();
m1.add();
m1.add();
m1.add();
console.log('/////////////////////////////');
var m2 = new CMyObj();
m2.add();
m2.add();
console.log('/////////////////////////////');
var m3 = new CMyObj();
m3.add();
console.log('/////////////////////////////');
m1.print();
m2.print();
m3.print();
}
}
</script>
</head>
<body>
<button id="btn1">button1</button>
</body>
</html>
输出结果如下:
n:1
n:2
n:3
/////////////////////////////
n:4
n:5
/////////////////////////////
n:6
/////////////////////////////
n value is:6
n value is:0
n value is:0
5 个解决方案
#1
var n=0;改为
this.n=0;
this.n=0;
#2
参考:《JavaScript权威指南(第6版)》8.6 闭包
“定义大多数函数时的作用域链在调用函数时依旧有效”。
待我再考虑一下,
“定义大多数函数时的作用域链在调用函数时依旧有效”。
待我再考虑一下,
#3
if ( CMyObj.prototype.add == undefined)
{
CMyObj.prototype.add = function(){
hello();
}
}
问题就在于这句。
new m1的时候,没有add方法,所以给创建了一个add方法,
new m2,new m3的时候,有了add方法,所以m1,m2,m3都是公用一个add方法,
而对于这个add方法来说,只能访问到m1里面的n,并不能访问到m2,m3里的n
而对于print方法,每次new都会重新创建一个匿名函数并指向给print属性,这个匿名函数可以访问当前构造方法里的n,所以对于m1,m2,m3都能直接访问到当前作用域下的n变量。
其实就是,定义add方法的时候由于是放在prototype原型上的方法,所有实例都是公用一个方法,而这个方法,只是在第一个new的时候创建,所以这个方法也就只能访问第一次调用构造方法的时候里的n变量。。
不知道解释的明白不?
#4
大概意思也能猜出来,add函数是从属于具体对象的私有成员。能不能找到相关语法引文或者用官方的表述陈词。
#5
找不到对应的官方陈述。
就是变量作用域相关内容,因为是定义在原型上的方法,所以所有实例化对象公用一个add方法。
而add方法只有在第一次new的时候会定义,所以对于add方法来说,访问到的n始终都是第一次调用构造方法时的那个n变量。
即使你是在add方法里调用了hello方法,对于m2,m3来说,这个hello方法还是在实例化m1时定义的那个hello方法。
只能解释到这里了,如果还不明白,那我也没办法给你解释了。
就是变量作用域相关内容,因为是定义在原型上的方法,所以所有实例化对象公用一个add方法。
而add方法只有在第一次new的时候会定义,所以对于add方法来说,访问到的n始终都是第一次调用构造方法时的那个n变量。
即使你是在add方法里调用了hello方法,对于m2,m3来说,这个hello方法还是在实例化m1时定义的那个hello方法。
只能解释到这里了,如果还不明白,那我也没办法给你解释了。
#1
var n=0;改为
this.n=0;
this.n=0;
#2
参考:《JavaScript权威指南(第6版)》8.6 闭包
“定义大多数函数时的作用域链在调用函数时依旧有效”。
待我再考虑一下,
“定义大多数函数时的作用域链在调用函数时依旧有效”。
待我再考虑一下,
#3
if ( CMyObj.prototype.add == undefined)
{
CMyObj.prototype.add = function(){
hello();
}
}
问题就在于这句。
new m1的时候,没有add方法,所以给创建了一个add方法,
new m2,new m3的时候,有了add方法,所以m1,m2,m3都是公用一个add方法,
而对于这个add方法来说,只能访问到m1里面的n,并不能访问到m2,m3里的n
而对于print方法,每次new都会重新创建一个匿名函数并指向给print属性,这个匿名函数可以访问当前构造方法里的n,所以对于m1,m2,m3都能直接访问到当前作用域下的n变量。
其实就是,定义add方法的时候由于是放在prototype原型上的方法,所有实例都是公用一个方法,而这个方法,只是在第一个new的时候创建,所以这个方法也就只能访问第一次调用构造方法的时候里的n变量。。
不知道解释的明白不?
#4
大概意思也能猜出来,add函数是从属于具体对象的私有成员。能不能找到相关语法引文或者用官方的表述陈词。
#5
找不到对应的官方陈述。
就是变量作用域相关内容,因为是定义在原型上的方法,所以所有实例化对象公用一个add方法。
而add方法只有在第一次new的时候会定义,所以对于add方法来说,访问到的n始终都是第一次调用构造方法时的那个n变量。
即使你是在add方法里调用了hello方法,对于m2,m3来说,这个hello方法还是在实例化m1时定义的那个hello方法。
只能解释到这里了,如果还不明白,那我也没办法给你解释了。
就是变量作用域相关内容,因为是定义在原型上的方法,所以所有实例化对象公用一个add方法。
而add方法只有在第一次new的时候会定义,所以对于add方法来说,访问到的n始终都是第一次调用构造方法时的那个n变量。
即使你是在add方法里调用了hello方法,对于m2,m3来说,这个hello方法还是在实例化m1时定义的那个hello方法。
只能解释到这里了,如果还不明白,那我也没办法给你解释了。