轻松理解js的函数和构造函数的区别

来源:互联网 发布:灵枢针灸免费网络课 编辑:程序博客网 时间:2024/05/18 07:06

转载地址:http://mp.weixin.qq.com/s?__biz=MzI0NjM5Mjc5NQ==&mid=2247483750&idx=1&sn=c1d6123f31c5cfc41c17fe108314a8c2&chksm=e9beb3d2dec93ac4b7b6e7614916a8cd79765975d911f8ed379a38a9956e5436a788c7f27b7a&mpshare=1&scene=23&srcid=0406xBlHwBkWGnSmmn3DhRm5#rd


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

如何轻松理解js的函数和构造函数的区别,这是个一直头大的问题,很多例子都没有清晰的描述清楚.。


在这里,我就用平常的道理来阐述一下,希望能理解清楚。


从这里开始入手吧

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>PHP葵花宝典(2017)-js推理篇</title>
<style type="text/css">
</style>

<script type="text/javascript">window.onload=function (){function myfunc(end_number){var sum=0;for (var i = 1; i <= end_number; i++) {sum+=i;};return sum;}var result=myfunc(36); //666alert(result);}
</script>

</head>
<body>
</body>
</html>


这是普通函数的定义和调用方式。看起来没什么特别的,但是往下看就有奇怪的东西了。


再做一个:


<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>PHP葵花宝典(2017)-js推理篇</title>
<style type="text/css">
</style>

<script type="text/javascript">window.onload=function (){       function Person(name){this.name=name;    } var p=new Person('niexiaoqian'); alert(p.name); //niexiaoqian}
</script>

</head>
<body>
</body>
</html>

你没发先一个很奇怪的现象吗?


你的这个函数里面并没有返回什么,也就是没有return ,但是你调用的时候却可以接受啊。


如:var p=new Person('niexiaoqian'); alert(p.name); //niexiaoqian


如果是一般函数的调用,没有返回东西,你接受不到任何东西,那就会有问题。


<!DOCTYPE HTML>
<html>
<head><meta charset="utf-8" />
<title>PHP葵花宝典(2017)-js推理篇</title>
<style type="text/css"></style>

<script type="text/javascript">window.onload=function (){
function Person(name){this.name=name;}
var p=Person('niexiaoqian');alert(p.name);}
</script>

</head>
<body>
</body>
</html>



所以,它限制了你那样的使用,就是让你用new的方式来启动它的另外处理的功能。


做成了当你new的时候,它就自动帮你返回东西了,你就可以继续的.出东西了,也就是说:


new的方式,它帮你自动返回了,不需要你在写return this;否则就错。


这样它可以在后续使用的过程中继续添加东西进行扩展,扩大了它的应用能力。


为了区别,它函数的首字母都大写。


当然,如果你做成了返回:


<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>PHP葵花宝典(2017)-js推理篇</title>
<style type="text/css"></style>

<script type="text/javascript">window.onload=function (){   function Person(name){this.name=name;return this;             }var p=Person('niexiaoqian'); alert(p.name);  }        
</script>

</head>
<body>
</body>
</html>

同样是弹出来了,但是使用的原理变了。


1:你这是同一个函数在调用两次,如果你打印两次的函数首地址,当然就一样;


2:你调用了两次,传递了不同的参数,但是它是同一个地方的啊,后来的就覆盖以前的了。当然两次打印就一样的了。


看打印例子:


<!DOCTYPE HTML>
<html>
<head><meta charset="utf-8" />
<title>PHP葵花宝典(2017)-js推理篇</title>
<style type="text/css"></style>

<script type="text/javascript">  
       window
.onload=function (){    function Person(name){
this.name=name;return this;}
             var p=Person('niexiaoqian');
     var p2=Person('xiaodie');      alert(p==p2);//true      alert(p.name);//xiaodie      alert(p2.name);//xiaodie      }                
 </script>
 
</head>
<body>
</body>
</html>

但是你如果是new的方式,它就是用那个模子造了两个对象出来,占据内存的不同的地方。当然就不一样的首地址,各自互不影响。


自然打印的就是另外的样子了。


看打印例子:


<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>PHP葵花宝典(2017)-js推理篇</title>
<style type="text/css"></style>

<script type="text/javascript">
   window.onload=function (){function Person(name){    this.name=name;    return this;}var p=new Person('niexiaoqian');var p2=new Person('xiaodie');alert(p==p2);//falsealert(p.name);//niexiaoqianalert(p2.name);//xiaodie}
</script>

</head>
<body>
</body>
</html>

现在的内存占据情况:造一个对象(存放在其他的地址哦),再造一个对象,又是存放到另外的地址,所以这是两个对象;


总的来说现在是有3个地方(函数自己,两个对象)占据内存了,以前只是一个地方(就是函数);所以它们3个的首地址自然是不一样的.


看例子:

<!DOCTYPE HTML>
<html>
<head><meta charset="utf-8" />
<title>PHP葵花宝典(2017)-js推理篇</title>
<style type="text/css">
</style>


<script type="text/javascript">
    window
.onload=function (){function Person(name){this.name=name;
return this;}var p=new Person('niexiaoqian');var p2=new Person('xiaodie');var p3=Person('xiaodie');alert(p==p2);//falsealert(p2==p3);//falsealert(p==p3);//false}
 </script>
 
</head>
<body>
</body>
</html>

全部都是false就可以证明。


它还可以造很多很多的对象,占据不同的内存地方。它就是要这样的做。因为这样做很有意义:


这样的使用,很容易在后面需要的时候继续添加成员方法来扩充具体某个对象的功能,不像以前那样只能去修改函数体本身(会影响其他地方的调用哦)表现为很灵活了。


这样的应用在现实中也有反映。从现实中的角度来看,如果你要造1000个金币,同时你想为每个金币添加不同的编号刻录在上面


你很有意义的做法就是:先做个模子,然后用模子快速的生成1000个金币的大概样子,然后再为每个金币去雕刻各自的编号。


你不会不做模子就直接去打造一个个的金币去了,那样太浪费时间了。因为如果是10000个呢?


所以这是高效的处理方式,所以它要先费力费时的造个金币模子出来,就是为了用该模子造出很多很多规格一样的具体金币对象出来,同时又可以为每个对象刻画不同的“编号”,既快速又省事,还能顺利实现需求。


而你直接去调用那个函数(不去实例化),就相当于你拿个金币模子到处在外面流传,这是不合法的哦,你肯定马上被抓了。


流传到外面的应该是用金币模子造好出来的那些金币,而不是印刷钱的印版啊。


所以,它就是要你用new的方式去调用,为此它还怕你分不清楚,这样的函数它都用首字母大写来标记,这种函数就叫“构造函数”。

0 0
原创粉丝点击