JS面向對象筆記二

来源:http://www.cnblogs.com/tandaxia/archive/2017/06/28/7079214.html
-Advertisement-
Play Games

菜單導航,《JS面向對象筆記一》, 參考書籍:阮一峰之《JavaScript標準參考教程》 一、構造函數和new命令 二、this關鍵字 三、構造函數和new命令 四、構造函數和new命令 五、構造函數和new命令 六、構造函數和new命令 七、構造函數和new命令 八、構造函數和new命令 一、構 ...


菜單導航,《JS面向對象筆記一》,  參考書籍:阮一峰之《JavaScript標準參考教程》

一、構造函數和new命令

二、this關鍵字

三、構造函數和new命令

四、構造函數和new命令

五、構造函數和new命令

六、構造函數和new命令

七、構造函數和new命令

八、構造函數和new命令

 

一、構造函數和new命令

1、構造函數

  • JavaScript語言的對象體系,不是基於“類”的,而是基於構造函數(constructor)和原型鏈(prototype)
  • 為了與普通函數區別,構造函數名字的第一個字母通常大寫,比如:  var Person = function(){  this.name = '王大錘';  }
  • 構造函數的特點: 
           a、函數體內部使用了this關鍵字,代表了所要生成的對象實例;
       b、生成對象的時候,必需用new命令調用此構造函數

2、new 

  作用:就是執行構造函數,返回一個實例對象 

var Person = function(name, age){
    this.name = name;
    this.age = age;
    this.email = '[email protected]';
    this.eat = function(){
        console.log(this.name + ' is eating noodles');
    }
}

var per = new Person('王大錘', 18);
console.log(per.name + ', ' + per.age + ', ' + per.email); //王大錘, 18, [email protected]
per.eat();  //王大錘 is eating noodles

執行new命令時的原理步驟:

  1. 創建一個空對象,作為將要返回的對象實例
  2. 將這個空對象的原型,指向構造函數的prototype屬性
  3. 將這個空對象賦值給函數內部的this關鍵字
  4. 開始執行構造函數內部的代碼

註意點:當構造函數裡面有return關鍵字時,如果返回的是非對象,new命令會忽略返回的信息,最後返回時構造之後的this對象;
  如果return返回的是與this無關的新對象,則最後new命令會返回新對象,而不是this對象。示例代碼:

console.log('---- 返回字元串 start ----');
var Person = function(){
    this.name = '王大錘';
    return '羅小虎';
}

var per = new Person();
for (var item in per){
    console.log( item + ': ' + per[item] );
}
//---- 返回字元串 start ----
//name: 王大錘

console.log('----- 返回對象 start ----');
var PersonTwo = function(){
    this.name = '倚天劍';
    return {nickname: '屠龍刀', price: 9999 };
}
var per2 = new PersonTwo();
for (var item in per2){
    console.log(item + ': ' + per2[item]);
}
//----- 返回對象 start ----
//nickname: 屠龍刀
//price: 9999
View Code

 

如果調用構造函數的時候,忘記使用new關鍵字,則構造函數裡面的this為全局對象window,屬性也會變成全局屬性,

則被構造函數賦值的變數不再是一個對象,而是一個未定義的變數,js不允許給undefined添加屬性,所以調用undefined的屬性會報錯。

示例:

var Person = function(){ 
    console.log( this == window );  //true
    this.price = 5188; 
}
var per = Person();
console.log(price); //5188
console.log(per);  //undefined
console.log('......_-_'); //......_-_
console.log(per.price); //Uncaught TypeError: Cannot read property 'helloPrice' of undefined
View Code

為了規避忘記new關鍵字現象,有一種解決方式,就是在函數內部第一行加上 : 'use strict';

表示函數使用嚴格模式,函數內部的this不能指向全局對象window, 預設為undefined, 導致不加new調用會報錯

var Person = function(){ 
    'use strict';
    console.log( this );  //undefined
    this.price = 5188; //Uncaught TypeError: Cannot set property 'helloPrice' of undefined
}

var per = Person(); 
View Code

另外一種解決方式,就是在函數內部手動添加new命令:

var Person = function(){ 
    //先判斷this是否為Person的實例對象,不是就new一個
    if (!(this instanceof Person)){
        return new Person();
    }
    console.log( this );  //Person {}
    this.price = 5188; 
}

var per = Person(); 
console.log(per.price); //5188
View Code

 

 

二、this關鍵字

var Person = function(){
    console.log('1111'); 
    console.log(this); 
    this.name = '王大錘';
    this.age = 18;

    this.run = function(){
        console.log('this is Person的實例對象嗎:' + (this instanceof Person) ); 
        console.log(this); 
    }
}

var per = new Person();
per.run();
/* 列印日誌:
1111
Person {}
this is Person的實例對象嗎:true
Person {name: "王大錘", age: 18, run: function}
*/

console.log('---------------');

var Employ = {
    email: '[email protected]',
    name: '趙日天',
    eat: function(){
        console.log(this);
    }
}

console.log(Employ.email + ', ' + Employ.name);
Employ.eat();
/* 列印日誌:
---------------
[email protected], 趙日天
Object {email: "[email protected]", name: "趙日天", eat: function}
*/
View Code

1、this總是返回一個對象,返回屬性或方法當前所在的對象, 如上示例代碼

2、對象的屬性可以賦值給另一個對象,即屬性所在的當前對象可變化,this的指向可變化

var A = { 
    name: '王大錘', 
    getInfo: function(){
        return '姓名:' + this.name;
    } 
}

var B = { name: '趙日天' };

B.getInfo = A.getInfo;
console.log( B.getInfo() ); //姓名:趙日天

//A.getInfo屬性賦給B, 於是B.getInfo就表示getInfo方法所在的當前對象是B, 所以這時的this.name就指向B.name
View Code

 3、由於this指向的可變化性,在層級比較多的函數中需要註意使用this。一般來說,在多層函數中需要使用this時,設置一個變數來固定this的值,然後在內層函數中這個變數。

示例1:多層中的this

//1、多層中的this (錯誤演示)
var o = {
    f1: function(){
        console.log(this); //這個this指的是o對象

        var f2 = function(){
            console.log(this);
        }();
        //由於寫法是(function(){ })() 格式, 則f2中的this指的是頂層對象window
    }
}

o.f1();
/* 列印日誌:
Object {f1: function}

Window {stop: function, open: function, alert: function, confirm: function, prompt: function…}
*/


//2、上面代碼的另一種寫法(相同效果)
var temp = function(){
    console.log(this);
}
var o = {
    f1: function(){
        console.log(this); //這個this指o對象
        var f2 = temp(); //temp()中的this指向頂層對象window
    }
}
o.f1(); 
/* 列印日誌
Object {f1: function}

Window {stop: function, open: function, alert: function, confirm: function, prompt: function…}
*/
//表示上面兩種寫法是一樣的效果,this的錯誤演示


//3、多層中this的正確使用:使用一個變數來固定this對象,然後在內層中調用該變數
var o = {
    f1: function(){
        console.log(this); //o對象
        var that = this;
        var f2 = function(){
            console.log(that); //這個that指向o對象
        }();
    }
}
o.f1();
/* 列印日誌:
Object {f1: function}
Object {f1: function}
*/
View Code

示例2: 數組遍歷中的this

//1、多層中數組遍歷中this的使用 (錯誤演示)
var obj = {
    email: '大錘@sina.com', 
    arr: ['aaa', 'bbb', '333'],
    fun: function(){
        //第一個this指的是obj對象
        this.arr.forEach(function(item){
            //這個this指的是頂層對象window, 由於window沒有email變數,則為undefined
            console.log(this.email + ': ' + item);
        });
    }
}

obj.fun(); 
/* 列印結果:
undefined: aaa
undefined: bbb
undefined: 333
 */

//2、多層中數組遍歷中this的使用 (正確演示,第一種寫法)
var obj = {
    email: '大錘@sina.com', 
    arr: ['aaa', 'bbb', '333'],
    fun: function(){
        //第一個this指的是obj對象
        var that = this; //將this用變數固定下來
        this.arr.forEach(function(item){
            //這個that指的是對象obj
            console.log(that.email + ': ' + item);
        });
    }
}
obj.fun(); //調用
/* 列印日誌:
大錘@sina.com: aaa
大錘@sina.com: bbb
大錘@sina.com: 333
 */


//3、多層中數組遍歷中this正確使用第二種寫法:將this作為forEach方法的第二個參數,固定迴圈中的運行環境
var obj = {
    email: '大錘@sina.com', 
    arr: ['aaa', 'bbb', '333'],
    fun: function(){
        //第一個this指的是obj對象
        this.arr.forEach(function(item){
            //這個this從來自參數this, 指向obj對象
            console.log(this.email + ': ' + item);
        }, this);
    }
}
obj.fun(); //調用
/* 列印日誌:
大錘@sina.com: aaa
大錘@sina.com: bbb
大錘@sina.com: 333
 */
View Code

 

4、關於js提供的call、apply、bind方法對this的固定和切換的用法

  1)、function.prototype.call(): 函數實例的call方法,可以指定函數內部this的指向(即函數執行時所在的作用域),然後在所指定的作用域中,調用該函數。
  如果call(args)裡面的參數不傳,或者為null、undefined、window, 則預設傳入全局頂級對象window;
  如果call裡面的參數傳入自定義對象obj, 則函數內部的this指向自定義對象obj, 在obj作用域中運行該函數

var obj = {};
var f = function(){
    console.log(this);
    return this;
}

console.log('....start.....');
f();
f.call();
f.call(null);
f.call(undefined);
f.call(window);
console.log('**** call方法的參數如果為空、null和undefined, 則預設傳入全局等級window;如果call方法傳入自定義對象obj,則函數f會在對象obj的作用域中運行 ****');
f.call(obj);
console.log('.....end.....');

/* 列印日誌:
....start.....
Window {stop: function, open: function, alert: function, confirm: function, prompt: function…}
Window {stop: function, open: function, alert: function, confirm: function, prompt: function…}
Window {stop: function, open: function, alert: function, confirm: function, prompt: function…}
Window {stop: function, open: function, alert: function, confirm: function, prompt: function…}
Window {stop: function, open: function, alert: function, confirm: function, prompt: function…}
**** call方法的參數如果為空、null和undefined, 則預設傳入全局等級window;如果call方法傳入自定義對象obj,則函數f會在對象obj的作用域中運行 ****
Object {}
.....end.....
*/
View Code

   call可以接收多個參數:第一個參數是this所指向的那個對象,後面的參數就是函數調用時需要的參數,模擬簡寫為:
  func.call(thisValue, arg1, arg2, ...); 示例:

var obj = {
    name: '張三', 
    age: 10,
    email: '張三@sina.com'
}

function change(name, age){
    this.name = name;
    this.age = age;
    console.log(this);
}

change.call(obj, '王大錘', '28'); 
//Object {name: "王大錘", age: "28", email: "張三@sina.com"}
View Code

 


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

-Advertisement-
Play Games
更多相關文章
  • 學過前端開發的地球人應該都瞭解,JavaScript分為三個部分:ECMAScript(JS語言本身基礎語法),DOM(文檔對象模型,應用程式編程介面),BOM(瀏覽器對象模型)。 BOM,實際上與瀏覽器有關係。因此瀏覽器廠商可以按照各自的想法隨意去擴展(基於window對象的擴展)。不過,擴展歸擴 ...
  • <meta charset="utf-8">告訴瀏覽器要用utf-8來解釋,同時,保存文檔時,編碼格式也要為utf-8格式。 ...
  • rem由來:font size of the root element,那麼rem是個單位,單位大小由它第一代老祖宗的font-size的大小決定。現在前端碼農們為了能在各個屏幕上看到一個健康的網頁在默默的犧牲著自己的健康,因為不僅要知道rem是個單位,更重要的是要知道怎麼能在不同解析度下呈現的頁面 ...
  • 在圖片比較多的網站總會看見,當瀏覽到那個位置,就載入那的圖片。 ...
  • 簡介 貝塞爾曲線是可以做出很多複雜的效果來的,比如彈跳球的複雜動畫效果,首先加速下降,停止,然後彈起時逐漸減速的效果。 使用貝塞爾曲線常用的兩個網址如下: 緩動函數:http://www.xuanfengge.com/easeing/easeing/ cubic-bezier:http://cubi ...
  • 1.如何使用vuex來保存數據(需要傳參的情況下) 實例說明:登錄->緩存用戶信息->跳轉到首頁->從state獲取用戶信息顯示在頁面上 step1: 新建store.js作為初始化vuex的主文件,可在裡面創建state對象,緩存數據欄位,初始化vuex, 目錄結構如下: store.js代碼如下 ...
  • 如果你是一個人在自學前端開發,或者是對前端開發有比較濃厚的興趣正想踏入前端領域,只要你在前端自學路上遇到了自己無法解決的技術難題,那麼儘管將你的疑惑交給我的小伙伴兒們吧,我們都是一群在前端自學路上摸爬滾打的有志青年,希望你可以來和我們共同交流。同時也希望你能獻出自己的一份力,幫助我的小伙伴兒們解決他 ...
  • 一. 簡介 一個用於顯示多種不同類型圖片的React組件,包括網路圖片、靜態資源、臨時的本地圖片、以及本地磁碟上的圖片(如相冊)等。從0.14版本開始,React Native提供了一個統一的方式來管理iOS和Android應用中的圖片。要往App中添加一個靜態圖片,只需把圖片文件放在代碼文件夾比如 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...