javascript语法好的进来看个问题

时间:2022-01-07 19:38:02


<!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;

#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


引用 3 楼 functionsub 的回复:
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变量。。

不知道解释的明白不?


大概意思也能猜出来,add函数是从属于具体对象的私有成员。能不能找到相关语法引文或者用官方的表述陈词。

#5


找不到对应的官方陈述。

就是变量作用域相关内容,因为是定义在原型上的方法,所以所有实例化对象公用一个add方法。

而add方法只有在第一次new的时候会定义,所以对于add方法来说,访问到的n始终都是第一次调用构造方法时的那个n变量。

即使你是在add方法里调用了hello方法,对于m2,m3来说,这个hello方法还是在实例化m1时定义的那个hello方法。

只能解释到这里了,如果还不明白,那我也没办法给你解释了。

#1


var 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


引用 3 楼 functionsub 的回复:
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变量。。

不知道解释的明白不?


大概意思也能猜出来,add函数是从属于具体对象的私有成员。能不能找到相关语法引文或者用官方的表述陈词。

#5


找不到对应的官方陈述。

就是变量作用域相关内容,因为是定义在原型上的方法,所以所有实例化对象公用一个add方法。

而add方法只有在第一次new的时候会定义,所以对于add方法来说,访问到的n始终都是第一次调用构造方法时的那个n变量。

即使你是在add方法里调用了hello方法,对于m2,m3来说,这个hello方法还是在实例化m1时定义的那个hello方法。

只能解释到这里了,如果还不明白,那我也没办法给你解释了。