如何讓你快速輕鬆理解js的函數和構造函數的區別

編程語言 HTML JavaScript PHP 寧哥實戰課堂 2017-04-08

如何輕鬆理解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); //666

  • alert(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>

如何讓你快速輕鬆理解js的函數和構造函數的區別

所以,它限制了你那樣的使用,就是讓你用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);//false

  • alert(p.name);//niexiaoqian

  • alert(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);//false

  • alert(p2==p3);//false

  • alert(p==p3);//false

  • }

  • </script>

  • </head>

  • <body>

  • </body>

  • </html>

全部都是false就可以證明。

它還可以造很多很多的對象,佔據不同的內存地方。它就是要這樣的做。因為這樣做很有意義:

這樣的使用,很容易在後面需要的時候繼續添加成員方法來擴充具體某個對象的功能,不像以前那樣只能去修改函數體本身(會影響其他地方的調用哦)表現為很靈活了。

這樣的應用在現實中也有反映。從現實中的角度來看,如果你要造1000個金幣,同時你想為每個金幣添加不同的編號刻錄在上面。

你很有意義的做法就是:先做個模子,然後用模子快速的生成1000個金幣的大概樣子,然後再為每個金幣去雕刻各自的編號。你不會不做模子就直接去打造一個個的金幣去了,那樣太浪費時間了。因為如果是10000個呢?

所以這是高效的處理方式,所以它要先費力費時的造個金幣模子出來,就是為了用該模子造出很多很多規格一樣的具體金幣對象出來,同時又可以為每個對象刻畫不同的“編號”,既快速又省事,還能順利實現需求。

而你直接去調用那個函數(不去實例化),就相當於你拿個金幣模子到處在外面流傳,這是不合法的哦,你肯定馬上被抓了。流傳到外面的應該是用金幣模子造好出來的那些金幣,而不是印刷錢的印版啊。

所以,它就是要你用new的方式去調用,為此它還怕你分不清楚,這樣的函數它都用首字母大寫來標記,這種函數就叫“構造函數”。

相關推薦

推薦中...