JavaScript入門

来源:https://www.cnblogs.com/xiukang/archive/2018/09/05/9325507.html
-Advertisement-
Play Games

JS介紹 數據輸出\輸入 JS變數 JS數據類型 進位介紹 數字(Number) 字元串(String) Boolean類型/Undefined類型/Null類型 類型轉換 運算符 流程式控制制 break與continue關鍵字 數組(Array) 函數(function) 函數中的幾個參數 sort ...


JS介紹

// JavaScript的發明人
// 布蘭登·艾奇(Brendan Eich),用了十天時間發明瞭JavaScript模型

// JavaScript簡稱JS

// JavaScript是什麼?
// 1.腳本語言
// 編譯語言:需要把代碼編譯成電腦所認知的二進位語言才能執行
// 腳本語言:不需要編譯,直接執行
// 2.解釋性語言
// 解釋性語言:遇到一行代碼就解釋一行代碼
// 其他語言:把所有代碼編譯完成後在執行代碼
// 3.動態類型的語言
// 4.基於對象的語言
// 5.弱類型語言
// 弱類型語言:聲明變數都用var,會自動辨別類型:var num = 10; var num2 = 10.23;
// 強類型語言:聲明變數的時候必須寫上對應變數的類型:int num = 10; double num2 = 10.23;

// JS分三個部分: 
// 1.ECMAScript js的基本語法
// 2.DOM  Document Object Model 文檔對象模型
// 3.BOM Browser Object Model 瀏覽器對象模型

// js代碼註意問題
// 1.如果script的標簽中有錯誤的js代碼,那麼這對script標簽就不會執行
// 2.如果有一個script標簽代碼錯誤,但它不會影響其他的script標簽
// 3.script標簽在頁面中可以多對出現
// 4.script標簽一般放在body標簽內容的最後,可以放在head中
// 5.如果script標簽引用外部js文件,那麼就不要在這對標簽裡面放任何js代碼

數據輸出\輸入

// 在瀏覽器彈出的提示框中顯示
alert();
// 在瀏覽器的控制臺中顯示
console.log();
// 在瀏覽器頁面中顯示
document.write();
// 在瀏覽器中彈出輸入框
prompt();

JS變數

/*什麼是變數:
 變數是電腦記憶體中存儲數據的標識符,根據變數名可以獲取到記憶體中存儲的數據*/

/*為什麼使用變數:
 使用變數可以方便的獲取或者修改記憶體的數據*/

// 變數的作用:
// 操作數據:存儲數據、讀取數據

/*變數名的規範:
一般以字母,$符號,下劃線開頭
變數名一般都是小寫,如果是多個單詞,那麼第一個單詞的首字母小寫,後面的單詞首字母大寫
變數名不能是關鍵字
區分大小寫*/

// 變數聲明
var  name;// 有var 有變數名字但沒有賦值

// 聲明多個變數
var name,age,sex;

// 變數的初始化:聲明變數同時賦值
var xiu = undefined;// 聲明變數沒有賦值預設為undefined:未定義
var number = 20;// 存儲一個數字(number)
var name = "修抗";// 存儲一個字元串(string) 字元串應該用單引號或者雙引號包裹起來
var flag = true;// 存儲一個真(true) 假(false)
var nll = null;// 存儲一個空(null)

// 聲明多個變數依次賦值
var num1,num2,num3;
num1 = 10;
num2 = 20;
num3 = 30;

// 聲明多個變數並賦值
var num1 = 10,num2 = 20,num3 = 30;

// 變數的交換(1)
var num1 = 10,num2 = 20;
var num3;//重新聲明一個變數
num3 = num1;//num3 = num1 = 10
num1 = num2;//num1 = num2 = 20
num2 = num3;//num2 = num3 = 10

// 變數的交換(2)一般適用於數字的交換
var num4 = 10,num5 = 20;
num4 = num4 + num5;//10+20=30
num5 = num4 - num5;//30-20=10
num4 = num4 - num5;//30-10=20

// 變數的交換(3)
var num6 = 10,num7 = 20;
num6 = num6 ^ num7;
num7 = num6 ^ num7;
num6 = num6 ^ num7;

JS數據類型

/*
原始數據類型:number,string,boolean,undefined,null,object
基本類型:number,string,boolean
複雜類型:object
空類型:undefined,null

基本類型的值在棧空間存儲
復類類型的值在堆空間存儲,然後在棧空間引用堆空間的地址
*/
// 獲取變數的數據類型
var xiu = "修抗";
console.log(typeof(xiu)); //string

進位介紹

// 八進位(數字前面加一個0代表八進位)
var num = 012;

// 十進位
var num2 = 10;

// 十六進位(數字前面加一個0x代表十六進位)
var num3 = 0xa;

/*二進位-->十進位
1----1----0----0----1----0----1----0----1(二進位)
256--128--64---32---16---8----4----2----1
256--128--0----0----16---0----4----0----1(十進位)
二進位:110010101 = 256+128+0+0+16+0+4+0+1 = 405:十進位
*/ 

/*二進位-->八進位
110----010----101(二進位)
6------2------5(八進位/每三位二進位為一組)
二進位:110010101 = 625:八進位
*/

/*二進位-->十六進位
1----1001----0101(二進位)
1----9-------5(十六進位/每四位二進位為一組)
二進位:110010101 = 195:十六進位
*/

/*十進位-->二進位
405-202-101-50--25--12--6---3---1
1---0---1---0---1---0---0---1---1(倒敘)
十進位:405 = 110010101:二進位
 */

數字(Number)

// 小數類型和整數類型都是數字類型(Number)

//數字的最大值和最小值
console.log(Number.MAX_VALUE);//最大值
console.log(Number.MIN_VALUE);//最小值

// Infinity 無窮大
// -Infinity 無窮小

// 小數的bug
console.log(0.1+0.2);//結果不是0.3而是0.30000000000000004

// 不要用NaN驗證NaN
var xiu;
console.log(xiu+10);//返回NaN
console.log("你好" == "我好");//false:都是字元串,但是字元串內容不一樣
console.log(xiu+10 == NaN);//false:都是NaN,但是裡面的值不一樣

// isNaN()判斷是否不是數字,如果不是數字返回true
console.log(isNaN(NaN));

字元串(String)

// 字元串可以使用單引號,也可以使用雙引號
var str = "xiu ";
var str2 = 'kang';

// 查看字元串的長度
console.log(str.length);

// 字元串拼接,用+鏈接
// 如果兩邊只要有一邊為字元串,那麼+就為拼接
// 如果兩邊都是數字。那麼就是算術功能
var str3 = "1";
var str4 = '2';
console.log(str3 + str4);//12

Boolean類型/Undefined類型/Null類型

// Boolean類型
// 布爾類型只有兩個值 true(真) false(假)
var flag = true;

// Undefined
// 表示聲明一個變數沒有賦值,變數只有聲明的時候值預設為undefined
var unde = undefined;

// null類型
// 表示一個空,變數的值如果為空,必須手動設置
var str = null;

類型轉換

// 其他類型轉為數字類型:三種方式
// parseInt();轉整數
console.log(parseInt("8sa"));//8
console.log(parseInt("as8"));//NaN
console.log(parseInt("8.9"));//8
console.log(parseInt("8.2as"));//8
console.log(parseInt("sa6.8"));//NaN

// parseFloat();轉小數
console.log(parseFloat("8sa"));//8
console.log(parseFloat("as8"));//NaN
console.log(parseFloat("8"));//8
console.log(parseFloat("8.9as"));//8.2
console.log(parseFloat("sa6.8"));//NaN

// Number();轉數字
console.log(Number("8sa"));//NaN
console.log(Number("as8"));//NaN
console.log(Number("8"));//8
console.log(Number("8.9as"));//NaN
console.log(Number("sa6.8"));//NaN

// 其他類型轉為字元串類型:兩種方式
// toString;不能轉換沒有意義的變數:null、undefined
var xiu = 10;
console.log(xiu.toString());

// String();
var kang = 20;
console.log(String(kang));

// 其他類型轉為布爾類型
// Boolean();
console.log(Boolean(0));//false
console.log(Boolean(""));//false
console.log(Boolean(null));//false
console.log(Boolean(undefined));//false

運算符

// x+y
// x和y是操作數 +是操作符

// 算術運算符(+、-、*、/、%)
10%4;//10除於4的餘數

// 一元運算符(++、--)
// 這個運算符只需要一個操作數就可以運算的表達式
// 前+ 後+ 前- 後-
var x = 2;
var y = 2;
console.log(x++ +3);//5,後+,先參與運算,運算結束後在+1
console.log(x);//3
console.log(++y +3);//6,前+,先+1,然後在參與運算
console.log(y);//3

// 二元運算符()
// 這個運算符需要兩個個操作數就可以運算的表達式

// 三元運算符()
// 這個運算符需要三個操作數就可以運算的表達式
// var 變數 = 表達式1 ? 表達式2 : 表達式3
// 如果表達式1結果為true,就執行表達式2,然後把表達式2的結果給變數
// 如果表達式1結果為false,就執行表達式3,然後把表達式3的結果給變數
var sear = true ? 1 : 2;//sear=1

// 複合運算符(+=、-=、*=、/=、%=)
var num;
num+=10;//num=num+10;

// 關係運算符(<、>、<=、>=、!=、==、===、!=、!==)
var xiu = "10";
var kang = 10;
console.log(xiu==kang);//兩個值都一樣所以為true
console.log(xiu===kang);//值一樣,但是類型不一樣所有為false

// 邏輯運算符($$與-並且、 ||或-或者、 !非-取反、)
console.log(true && true);//兩個為true則為true
console.log(true || false);//一個為true則為true
console.log(!false);//false為true,true為false

/*
運算符的優先順序
1.() 優先順序最高
2.一元運算符 ++ -- !
3.算術運算符 先* / 後 + -
4.關係運算符 < <= > >=
5.相等運算符 == != === !==
6.邏輯運算符 先&& 在||
7.賦值運算符 =
 */

流程式控制制

// 流程式控制制:代碼的執行過程

// 流程式控制制的三種方式:
// 1.順序結構
// 從上到下,從左往右執行的順序叫順序結構(不嚴謹)
// var xiu = 2;(不嚴謹的原因:先找到2,然後在將2賦值給xiu)

// 2.分支結構

// if語句
/*
if(表達式1) {
    代碼塊1
}else if(表達式2) {
    代碼塊2
}else {
    代碼塊3
}
先運行表達式1,如果表達式1為true就執行的代碼塊1,如果為false就執行表達式2
如果表達式2,如果表達式2為true就執行的代碼塊2,如果為false就執行代碼塊3
else if()可以多次出現,也可以不寫
else 只能出現一次,也可以不寫
*/
var x = prompt("請輸入數字");//prompt()彈出一個輸入框
if(x > 5){
    console.log("大於5");
}else if(x < 5) {
    console.log("小於5");
}else if(x == 5) {
    console.log("等於5");
}else {
    console.log("請輸入數字");
}

// switch-case
/*
switch(表達式){
    case 值1: 代碼塊;break;    
    case 值2: 代碼塊;break;    
    case 值3: 代碼塊;break;    
    default:代碼4;   
}
獲取表達式的值,然後和值依次比較,如果和值相等執行相對應的代碼塊,遇到break跳出switch語句
如果和值都不相等,那麼就執行default語句
表達式的值跟case的值比較是嚴格模式的比較(===)
default可以省略
break可以省略:省略後不會跳出語句 會依次往下執行
 */
var y = prompt("請輸入1到3的整數");
switch(y){
    case "1":console.log(y);
    break;//該語句為跳出語句
    case "2":console.log(y);
    break;
    case "3":console.log(y);
    break;
    default:console.log("請輸入1到3的整數");
}

// 三元表達式

// 3.迴圈結構
// while
/*
var 變數 = 0;
while(條件){
    迴圈體;
    計數器;
}
如果條件為false,就不執行while大括弧裡面的內容
如果條件為true,就執行迴圈體,然後執行計數器,迴圈結束後計數器+1,然後又去判斷條件,直到條件為false停止迴圈
*/
var xiu = 0;//計數器
while(xiu<10){
    console.log(xiu);//迴圈體
    xiu++;//計數器+1
}

// do-while
/*
do {
    迴圈體
}while(條件);
先執行迴圈體,然後在判斷條件是否成立,如果為true繼續執行迴圈體,然後在判斷條件,直到條件為false跳出迴圈
*/
var kang = 0;
do {
    console.log(kang);
    kang++;
}while(kang<0);

// for
/*
for(表達式1;表達式2;表達式3;){
    迴圈體;
}
先獲取表達式1的值,然後判斷表達式2,如果為false跳出迴圈,如果為true就執行迴圈體然後在執行表達式3,然後繼續執行表達式2,直到條件為false
*/
for (var i = 1; i <= 10; i++) {
    console.log(i);
}

 break與continue關鍵字

// break關鍵字
// 作用:在迴圈中使用,遇到break則跳出當前迴圈
while(true){
    console.log("修抗");
    break;//本來是一個死迴圈,但是遇到break就跳出迴圈,所有就執行一次
}

// continue關鍵字
// 作用:在迴圈中使用,遇到continue直接執行下次迴圈
// 輸出10以內的奇數
var i = 0;
while(i<10){
    if(i%2==0){
        i++;
        continue;//如果為偶數就繼續下次迴圈
    }
    document.write(i);
    i++;
}

數組(Array)

// 數組:存儲一組有序的數據

// 作用:可以一次性存儲多個數據

// 數組的定義:
/*
1.通過構造函數創建數組
var 數組名 = new Array();
var 數組名 = new Array(長度);
如果Array中只有一個值(整數),那麼這個值就是該數組的長度(元素就個數)
如果有多個值,那麼這些值就是該數組的數據(數組的長度就是有多少個值)
 */
var array = new Array();//創建一個空數組,沒有數據
var array2 = new Array("25");//如果數組中沒有數據,但有長度,那麼數組的每個值就是undefined

/*
2.通過字面量的方式創建數組
var array = [];
 */
var array3 = [];//創建空數組
var array4 = [3,34,46,7];//創建數組並添加數據

/*
數組元素:就是數組中存儲的數據
數組個數:就是數組中元素的個數
數組下標:從0開始,到數組長度減1結束
通過下標設置數組元素值:數組名[下標] = 值
通過下標訪問數組元素值:數組名[下標]
 */

// 獲取數組的長度
array.length;

// 註意: 數組中的數據類型可以不一樣,但一般存儲一樣的數據,數組的長度可以任意改變
var array5 = [10,"哈哈",true,undefined,null,new Object()];

// 遍曆數組
var array6 = [2,5,72,58,3,52];
for(var i=0;i<array6.length;i++){
    console.log(array6[i]);
}

// 求數組的和
var array7 = [1,2,3,4,5];
var sum = 0;
for(var i=0;i<array7.length;i++){
    sum+=array7[i];
}
console.log(sum);

// 求數組的平均值
var array8 = [1,2,3,4,5];
var avg = 0;
for(var i=0;i<array8.length;i++){
    avg+=array8[i];
}
console.log(avg/array8.length);

// 求數組的最大值
var array9 = [1,2,3,4,5];
var max = array9[0];
for(var i=1;i<array9.length;i++){
    if(max<array9[i]){
        max=array9[i];
    }
}
console.log(max);

// 數組的倒敘
var array10 = [1,2,3,4,5];
for(var i=array10.length-1;i>=0;i--){
    console.log(array10[i]);
}

// 去掉數組中的0
var array11 = [1,0,3,0,5];
var newArray11 = [];
for(var i=0;i<array11.length;i++){
    if(array11[i] != 0){ 
        newArray11[newArray11.length] = array11[i];
    }
}
console.log(newArray11);

// 冒泡排序:把所有數據按照一定順序進行排序(從大到小,從小到大)
var arr = new Array(3,36,2,47,42,436,54);
for (var i=0;i<arr.length-1;i++) {
    for(var j=0;j<arr.length-1-i;j++){
        if(arr[j]>arr[j+1]){
            var tame = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = tame;
        }
    }
}
console.log(arr);

 函數(function)

/*
函數:將重覆的代碼進行封裝,在需要的時候進行調用

定義函數:
function 函數名(){
    函數體;
}
調用函數:
函數名();

函數參數:
定義函數的時候,函數名後面的小括弧里的變數就是參數
function 函數名(x,y){
    函數體;
}

形參:定義函數時小括弧裡面的參數
function 函數名(x,y){
    函數體;
}
實參:調用函數時小括弧裡面的參數
函數名(x,y);

函數的返回值:
在函數內部有return關鍵字並且關鍵字後面有內容,那麼這個內容就是返回值
在調用的時候,如果需要返回值,就定義變數接收就行了
function 函數名(){
    return 520;
}
var fun = 函數名();//此時fun變數的值就是函數返回的值

無參數無返回值的函數
function xiu(){
    console.log("修抗");
}
無參數有返回值的函數
function xiu(){
    return "修抗";
}
有參數無返回值的函數
function xiu(x,y){
    console.log(x+y);
}
有參數有返回值的函數
function xiu(x,y){
    return x+y;
}

命名函數:函數有名字
匿名函數:函數沒有名字

定義匿名函數:
function(){
    函數體;
}
匿名函數不能直接調用,需要賦值給變數才能調用(這就是函數表達式)
var fun = function(){
    函數體;
}
fun();//在變數後面添加小括弧就可以調用匿名函數了

函數的自調用:
(匿名函數)();
(function(){alert("修抗");})();

函數做為參數使用:
如果一個函數作為參數使用,那麼這個參數(函數)就是回調函數
function xiu(){
    kang();
}
function kang(){
    函數體;
}

函數做為返回值使用:
function xiu(){
    return function(){
        函數體;
    };
}
var kang = xiu();//將xiu的返回值賦值給變數,現在變數就是一個函數
kang();//直接加小括弧掉用就行了

註意:
函數一旦重名,就會把前面的函數覆蓋
匿名函數就不會出現重名的問題
形參和實參的個數可以不一致
函數沒有明確返回值,但調用的時候接收了,那麼接收的值為undefined
沒有明確返回值:沒有return或者return後面沒有跟任何內容
return後面的代碼不會執行
函數也有數據類型:function類型
 */

函數中的幾個參數

function f1(x,y){
    //獲取的函數的名字,只讀
    console.log(f1.name);
    // 獲取實參的個數
    console.log(f1.arguments.length);
    // 獲取形參的個數
    console.log(f1.length);
    // 調用者,如果該函數被其他函數調用,那麼該屬性就輸出其他函數的源碼
    console.log(f1.caller);
}
f1(1,2);

 sort()

// sort()對數組的元素進行排序,並返回數組
var arr = ["dfg","dgh","dsgar"];
arr.sort(function(x,y){
    if(x>y){
        return 1;
    }else if(x==y){
        return 0;
    }else {
        return -1;
    }
});
console.log(arr);

閉包

/*
閉包的概念:
在函數A中有一個函數或者對象,該函數或者對象可以訪問函數A中定義的變數或者數據,此時形成了閉包
閉包的模式:
函數模式的閉包,對象模式的閉包
閉包的作用:
緩存數據,延長作用域鏈
閉包的優點缺點:
優點:可以緩存數據,缺點:緩存數據的同時不能釋放空間
局部變數是在函數中,函數使用結束後,局部變數就會被自動釋放
閉包後,裡面的局部變數的使用作用域就會被延長,不會被釋放
 */
// 函數模式的閉包:在一個函數中有一個函數
function f1(){
    var num = 10;
    function f2(){
        console.log(num);
    }
    f2();
}
f1();
// 對象模式的閉包:在一個函數中有一個對象
function f3(){
    var num = 3;
    var obj = {age:num};
    console.log(obj.age);
}
f3();

// 列子:
function person(){
    var num = 1;
    return function(){
        num++;
        console.log(num);
    }
}
var per = person();
per();//2
per();//3
per();//4

沙箱

作用域

/*
局部變數:在函數內部定義的變數叫局部變數,只能在函數內部才能使用
全局變數:除了函數以外在其他任意位置定義的變數叫全局變數,可以在頁面任意位置使用
隱式全局變數:聲明變數的時候沒有var就是隱式全局變數(可以在頁面任意位置使用)

局部作用域:局部變數的使用範圍
全局作用域:全局變數的使用範圍
塊級作用域:大括弧裡面定義的變數只能在當前大括弧裡面使用,而js不支持塊級作用域(函數除外)

註意:
定義全局變數,只要頁面不關閉就會一直占空間,消耗記憶體(就是卡),只有在頁面隔壁的時候才會釋放空間
定義局部變數,就只有在調用的時候占空間,調用完後就會釋放空間(所以儘量使用局部變數)
全局變數不能被刪除而隱式全局變數可以被刪除,刪除變數(delete 變數名;)

作用域鏈:
var sum = 0;
function f1(){
    var sum = 1;
    f2();
    function f2(){
        var sum = 2;
        f3();
        function f3(){
            var sum = 3;
            alert(sum);
        }
    }
}
如果當前沒有變數就會去上一級找變數,沒有繼續去上一級,直到全局變數,這就是作用域鏈
 */

預解析

// 預解析:提前解析代碼

// 提前解析變數
console.log(sum);//輸出undefined
var sum = 0;
/*
理解:瀏覽器幫我們做的事,瀏覽器將聲明變數提前了,但沒有把賦值提前
var sum;
console.log(sum);//因為聲明變數沒有賦值,所以就是undefined
sum = 0;
 */

// 提前解析函數
xiu();
function xiu(){
    console.log("愛心");
}
/*
理解:瀏覽器幫我們做的事,瀏覽器將聲明的函數提前了
function xiu(){
    console.log("愛心");
}
xiu();
 */

// 同時解析函數和變數
kang();
function kang(){
    console.log(str);
}
var str = "埃辛";
/*
理解:瀏覽器幫我們做的事,瀏覽器先將聲明的變數提前然後在將聲明的函數提前
var str;
function kang(){
    console.log(str);
}
kang();
str = "埃辛";
 */

函數聲明出現的問題

/*
函數的聲明
function f1(){}

函數表達式
var f1 = function(){};
 */
if(true){
    function f1(){
        console.log("true");
    }
}else {
    function f1(){
        console.log("false");
    }
}
f1();
// 在IE10及之前輸出的結果都是false,因為會把函數的聲明提前
// 解決辦法就是使用函數表達式,函數表達式不會被提前
 var f2;
 if(true){
    f2 = function(){
        console.log("true");
    }
}else {
    f2 = function(){
        console.log("false");
    }
}
f2();

創建對象

/*
編程思想:
把一些生活中的經驗融入到程式中

面向過程:
每件事的具體過程要知道,註重的是過程

面向對象:
所有的事都用對象來做,註重的是結果

面向對象的基本特性:
封裝,繼承,多態(抽象性)

對象的特征:
有屬性或者方法

面向對象的編程思想:
根據需求,找出相關的對象,總結對象的特征和行為,把特征變成屬性,行為變成方法,然後定義構造函數,實例化對象,通過對象調用屬性或者方法,完成對應的需求,這就是編程思想 js不是面向對象的語言,但是可以模擬面向對象的思想 js是一門基於對象的語言
*/ // 第一種方式創建對象:調用系統自帶的構造函數 new Object() var obj = new Object(); obj.name = "修抗"; //添加屬性1 obj.sex = "男"; //添加屬性2 obj.xiu = function(){ //添加方法1 console.log("方法1"); } obj.kang = function(){ //添加方法2 console.log("方法2"); } // 調用屬性的兩種方式 console.log(obj.name); //對象.屬性 console.log(obj["sex"]); //對象["屬性"] // 調用方法的兩種方式 obj.xiu(); //對象.方法名() obj["kang"](); //對象["方法名"]() // 第二種方式創建對象:自定義一個構造函數,然後在創建對象 // 創建自定義構造函數,構造函數與函數的區別在於首字母是否大寫 function Person(name,age){ //添加屬性 this.name = name; this.age = age; //添加方法 this.type = function(){ console.log("我叫"+this.name+",今年"+this.age+"歲"); }; } //調用自定義的構造函數創建對象,同時對屬性進行初始化(實例化對象) var obj2 = new Person("修抗",24); // 調用屬性和方法 console.log(obj2.name); obj2.type(); // 第三種方式創建對象:工廠模式創建對象 // 把創建對象的代碼放在函數中,返回值就是這個對象, function createObject(name,age){ var obj3 = new Object(); obj3.name = name; obj3.age = age; obj3.xiu = function(){ console.log("我叫"+this.name+",今年"+this.age+"歲"); } return obj3; } var kang = createObject("修抗",20); kang.xiu(); // 第四種方式創建對象:字面量創建對象 // 方式1: var obj4 = {}; obj4.name = "修抗";// 添加屬性 obj4.type = function(){// 添加方法 alert("方法"); } // 方式2: var obj5 = { name: "修抗", type:function(){ alert("方法2") } };

遍歷對象的屬性和值

var obj = {
    name : "修抗",
    age : 20
}
for(key in obj){
    console.log(key);//屬性
    console.log(obj[key]);//
}

工廠模式和自定義構造函數的區別

// 自定義創建對象
function Penson(name){
    this.name = name;
}
var obj = new Penson("修抗");
console.log(obj.name);

//工廠模式創建對象
function createObj(){
    var obj2 = new Object();
    obj2.name = "愛心";
    return obj2;
}
var obj3 = createObj();
console.log(obj3.name);
/*
自定義創建對象與工廠模式創建對象的區別

自定義創建對象:
函數名是大寫(首字母)
沒有new
沒有返回值
this是當前對象
通過new的方式創建對象

工廠模式創建對象:
函數名是小寫
有new
有返回值
new之後的對象是當前對象
直接調用函數就可以創建對象

他們的共同點:都是函數,都可以創建對象,都可以傳入參數
 */

構造函數和實例對象之間的關係

// 自定義構造函數創建對象
function Person(name){
    this.name = name;
 }
 //實例化對象
var obj = new Person("修抗");
// console.dir()可以把對象的構造顯示出來
console.dir(Person);//輸出構造函數
console.dir(obj);//輸出實例化對象
console.log(Person.prototype.constructor == Person);//true
console.log(obj.__proto__.constructor == Person);//true
console.log(obj.constructor == Person);//true
console.log(obj instanceof Person);//true
/*
實列對象和構造函數的關係
實列對象是通過構造函數來創建的,創建的過程叫實例化
判斷對象的數據類型(自定義對象)
1. 通過構造器的方式:
實列對象.構造器(constructor) == 構造函數的名字
obj.constructor == Person
2. 對象 instanceof 構造函數名字
obj instanceof Person
 */

構造函數創建對象帶來的問題

function Person(name,age){
    this.name = name;
    this.age = age;
    this.type = function(){
        console.log("修抗");
    }
}
var obj1 = new Person("修抗",20);
var obj2 = new Person("修抗",20);
// 他們指向的方法不是同一個方法,那麼就開闢了不同的空間,浪費記憶體
console.log(obj1.type == obj2.type);//false
// 解決辦法
function f1(){
    console.log("修抗");
}
function Person2(name){
    this.name = name;
    this.type = f1;
}
var obj3 = new Person2("修");
var obj4 = new Person2("修");
// 此時他們指的是同一個方法,節省空間,但函數可能重名,發生不必要的問題
console.log(obj3.type == obj4.type);//true
// 可以使用原型解決該辦法:原型的作用之一就是數據共用,節省記憶體空間

原型及原型鏈

//構造函數
function Person(name,age){
    this.name = name;
    this.age = age;
}
// 實例化對象並初始化
var p1 = new Person("修抗",20);
var p2 = new Person("愛惜",20);
console.dir(Person);//查看構造函數的結構
console.dir(p1);//查看實列對象的結構
/*
實列對象中有兩個屬性(這兩個屬性是通過構造函數獲取的)
構造函數中並沒有name和age這兩個屬性

實列對象中有個屬性,__proto__,也是對象,叫原型,不是標準屬性,瀏覽器使用的
構造函數中有個屬性,prototype,也是對象,叫原型,是標準屬性,程式員使用的

constructor:構造函數
*/
// 實列對象和構造函數的原型指向的是同一個構造函數
console.log(Person.prototype.constructor == p1.__proto__.constructor);//true
// 通過原型添加方法
Person.prototype.type = function(){
    console.log("修抗");
}
// 因為他們指向的是同一個原型裡面的構造函數裡面的方法,是同一個方法
console.log(p1.type == p2.type);//true

// 原型鏈:是一種關係,實列對象和原型對象之間的關係,關係是通過原型(__proto__)來聯繫的

改變原型的指向和添加改變後的原型方法

function Person(){};
Person.prototype.sayHi = function(){
    console.log("打招呼");
};
function Student(){};
Student.prototype.eat = function(){
    console.log("牛皮");
};
Student.prototype = new Perso

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先現在Vue中引入clipboard 在需要使用的組件中import 引入clipboard clipboard的實際使用 不論是單按鈕複製還是多按鈕複製,一定要在頁面載入DOM完成後先New出來具有複製功能的按鈕,如果在函數內再New那麼可能會出現點擊複製按鈕兩次,才複製成功的現象,如下: 綁定 ...
  • 在app.modlues.ts文件中修改 ...
  • //來自 https://www.cnblogs.com/lhl66/p/8021730.html 侵刪el:element 需要獲取的元素,一定是HTML中的根容器元素 data:用於數據的存儲 methods:用於存儲各種方法 數據綁定字面量只載入一次{{* msg}} data裡面可以進行簡單 ...
  • 何為滾動視差 視差滾動(Parallax Scrolling)是指讓多層背景以不同的速度移動,形成立體的運動效果,帶來非常出色的視覺體驗。 作為網頁設計的熱點趨勢,越來越多的網站應用了這項技術。 通常而言,滾動視差在前端需要輔助 Javascript 才能實現。當然,其實 CSS 在實現滾動視差效果 ...
  • 參考鏈接:https://segmentfault.com/q/1010000010714863 ...
  • 原因: 元素設置了float屬性後,就會脫離文檔流,當 包含框 的高度小於 浮動框 的時候,會出現高度塌陷。因此才需要清除浮動! 表現如圖:包括框container已經包不住float的圖片了! 清除浮動方法: 1:給 包含框 添加 after偽元素清除浮動。代碼: 2:使用BFC, 原理:讓浮動塊 ...
  • 在上一篇《前端面試 - 演算法篇(二分法)》的評論中,有朋友提出了一個“迴圈殺人游戲” 就在我為之苦惱的時候,一位同事在我身旁經過,突然說了一句:“咦,這不是約塞夫問題嗎?” 一、面試題 原題目不太明朗(一號到底殺不殺?) 於是把題目優化一下,更接近於原本的約塞夫問題 假設有100人,分別編號 1~1 ...
  • left right aaa ... ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...