JavaScript中的this關鍵字的用法和注意點

JavaScript中的this關鍵字的用法和注意點

1、this關鍵字的用法

this通常用於指向對象(綁定對象);javascript

01、在普通函數調用中,其內部的this指向全局對象(window);html

function funcName(){
    this.name = 'Jack';
    console.log(this);// Window
}
funcName();
console.log(window.name);// Jack
console.log(this.name);// Jackjava

上述代碼先聲明一個函數名爲funcName的函數,給函數內部的對象添加屬性name,並打印this的指向(window),分別打印this的屬性值和全局對象(window)的屬性值,兩者相等說明this指向全局對象(window);git

 

02、在構造函數調用中,其內部的this指向新建立的對象github

function Person() {
    this.name = '郭嘉';
    console.log(this);// Person {name: "郭嘉"}
}
var p1 = new Person();
console.log(p1.name); // 郭嘉
console.log(window.name);// 數組

上述代碼先聲明一個函數名爲Person的構造函數,給構造函數內部的對象添加屬性name,並打印this的指向(新建立的對象:Person {name: "郭嘉"}),用Person構造函數實例化一個對象p1,分別打印p1的屬性值和全局對象(window)的屬性值,兩者不相等說明this指向的是新建立的對象(Person {name: "郭嘉"})而不是全局對象(window);app

 

補充:使用new關鍵字建立構造函數的實例對象的系統內部流程函數

/*new關鍵字建立構造函數的實例的系統內部流程*/
//001 使用new 關鍵字在內部默認建立一個對象
//002 在構造函數內部,把默認建立的對象賦值給this
//003 經過this來設置對象的屬性和方法
//004 默認把新建立的對象返回給咱們
function Person() {
    //var this = new Object();//使用new 關鍵字在內部默認建立一個對象,並在構造函數內部,把默認建立的對象賦值給this
    this.name = '郭嘉';//經過this來設置對象的屬性和方法
    console.log(this);// Person {name: "郭嘉"}
    //return this;// 默認把新建立的對象返回給咱們
}測試

 

03、在對象的方法調用中,其內部的this指向調用的對象自己this

//以對象的方法來進行調用
var obj = {
    name:"張三", // 對象的屬性
    getName:function () { // 對象的方法
        console.log(this);// Object {name: "張三"}
    }
};
obj.getName();// 對象的方法調用
console.log(obj.name); // 張三
console.log(window.name);//

上述代碼先聲明一個對象名爲obj的對象,給對象添加屬性name,和方法getName,並在方法內部打印this的指向(對象自己:Object {name: "張三"}),調用對象的方法,打印this的指向是對象自己(Object {name: "張三"})而不是全局對象(window);

 

04、在事件處理中,其內部的this指向產生這個事件源的對象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id='btn'>click</button>
<script>
   var btn = document.getElementById('btn');// 獲取idbtn的標籤
   btn.onclick = function () {// 按鈕點擊事件
       console.log(this);

// <button id='btn'>click</button>
   };
</script>
</body>
</html>

上述代碼先用html建立一個按鈕,再給這個按鈕添加一個點擊事件,並打印this的指向(<button id =btn>click</button>),得出結論是this指向產生事件源的對象(<button id =btn>click</button>);

 

05、在定時器中其內部的this指針指向window對象

function Person() {
    // 備份指針
    console.log(this); // Person {}
    var self = this;
    setInterval(function () {
        console.log(self);// Person {}
        console.log(this);// Window
    }, 20);
}
new Person();

上述代碼先建立一個person函數,再用self來備份一下this指針,再建立定時器,定時器內部的this永遠指針指向window對象,有時候咱們咱們要用到指定的對象不是window對象,咱們能夠經過備份指針來實現;

 

06、經過call或者apply方式調用中(函數上下文),this指向的是當前的上下文,主要是改變this的指向

call方法: 傳入的參數數量不固定

第一個參數是要綁定給this的值(即函數體內this對象的指向)

第二個參數開始日後,每一個參數都依次的傳入做爲函數的參數

 

apply: 接收兩個參數

第一個參數是要綁定給this的值(即函數體內this對象的指向)

第二個就是一個參數數組

function Person() {
    this.name = 'Jack';
}
function Boy() {
    Person.call(this);
    console.log(this);// Boy {name: "Jack"}
}
var b1 = new Boy();

上述代碼建立兩個構造函數PersonBoy,使用call方法讓Person構造函數中的this指向Boy構造函數,至關於把Person構造函數內對象的屬性和方法深拷貝一份(包括引用類型:指針和堆空間的數據)

 

var obj = {
    name:"張三",
    getName:function (param1,param2) {
        console.log(this.name,param1,param2);
    }
}

obj.getName("123","456");      //張三 123 456

var obj2 = {name:"李四"};
obj.getName.call(obj2); //打印李四 undefined undefined

obj.getName.call(obj2,"測試字符串01","測試的字符串02"); // 李四 測試字符串01 測試的字符串02
obj.getName.apply(obj2,["123","456"]);   // 李四 123 456

上述代碼先建立一個對象obj並添加屬性name和方法getName,調用自身的方法得出的結果(張三 123 456),再建立一個對象obj2,添加屬性name,obj.getName.call(obj2);這句話的意思是obj的方法getName借給obj2使用,其obj方法內部的this指向obj2;得出的結果是李四 undefined(沒有傳參)  undefined(沒有傳參)call方法主要是改變this的指向;apply的方法做用和call同樣,只是傳的參數不同,call能夠只傳一個參數(要綁定給this的值),也能夠傳多個;而apply接收兩個參數(要綁定給this的值[],第二個參數是數組,數組的長度不定。

 

2、 this關鍵字用法的注意點

This的丟失問題

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="box"></div>
<script>
 var box = document.getElementById('box');// 獲取標籤
 var getId = document.getElementById;//
 var box = getId('box');// Uncaught TypeError: Illegal invocation (未捕獲的類型錯誤)
 console.log(box);
</script>
</body>
</html>

上述代碼先在html中建立一個idboxdiv,而後再js中獲取標籤,有時候咱們嫌獲取標籤的方法太長了,想要縮減一下(var getId = document.getElementById),再調用,然而上述代碼調用時則報錯了!緣由是方法內部的this指針丟失了,原先document.getElementById內部實現中用到this指針,其指向document對象,而getId調用時是按普通函數調用的,其內部的this指針指向window對象,因此執行到這一步的時候報錯!

 

如今用apply方法來修正this的指向

//借用apply來修正this
document.getElementById = (function (func) {
    return function () {
        return func.apply(document,arguments);
    }
})(document.getElementById);
var getId = document.getElementById;
/*上句代碼等同於下面這句代碼
var getId = function () {
    return document.getElementById.apply(document,arguments);
}*/
var box = getId('box');       //不會報錯
console.log(box);// <div id="box"></div>

上述代碼先在document.getElementById方法內部添加一個讓this指針一直指向document對象的操做;document.getElementById =(function(func){})(document.getElementById);這是一個當即執行函數,把document.getElementById看成實參傳進去,而函數內部則返回另外一個函數,而這個函數內部則執行改變this指向的操做document.getElementById.apply(document,arguments);意思是讓this永遠指向document對象;arguments指的是傳進去的實參Id(box);

 

3、結論

This關鍵字永遠指向實際調用者

 

 

 

JavaScript中的this關鍵字的用法和注意點

1、this關鍵字的用法

this通常用於指向對象(綁定對象);

01、在普通函數調用中,其內部的this指向全局對象(window);

function funcName(){
    this.name = 'Jack';
    console.log(this);// Window
}
funcName();
console.log(window.name);// Jack
console.log(this.name);// Jack

上述代碼先聲明一個函數名爲funcName的函數,給函數內部的對象添加屬性name,並打印this的指向(window),分別打印this的屬性值和全局對象(window)的屬性值,兩者相等說明this指向全局對象(window);

 

02、在構造函數調用中,其內部的this指向新建立的對象

function Person() {
    this.name = '郭嘉';
    console.log(this);// Person {name: "郭嘉"}
}
var p1 = new Person();
console.log(p1.name); // 郭嘉
console.log(window.name);//

上述代碼先聲明一個函數名爲Person的構造函數,給構造函數內部的對象添加屬性name,並打印this的指向(新建立的對象:Person {name: "郭嘉"}),用Person構造函數實例化一個對象p1,分別打印p1的屬性值和全局對象(window)的屬性值,兩者不相等說明this指向的是新建立的對象(Person {name: "郭嘉"})而不是全局對象(window);

 

補充:使用new關鍵字建立構造函數的實例對象的系統內部流程

/*new關鍵字建立構造函數的實例的系統內部流程*/
//001 使用new 關鍵字在內部默認建立一個對象
//002 在構造函數內部,把默認建立的對象賦值給this
//003 經過this來設置對象的屬性和方法
//004 默認把新建立的對象返回給咱們
function Person() {
    //var this = new Object();//使用new 關鍵字在內部默認建立一個對象,並在構造函數內部,把默認建立的對象賦值給this
    this.name = '郭嘉';//經過this來設置對象的屬性和方法
    console.log(this);// Person {name: "郭嘉"}
    //return this;// 默認把新建立的對象返回給咱們
}

 

03、在對象的方法調用中,其內部的this指向調用的對象自己

//以對象的方法來進行調用
var obj = {
    name:"張三", // 對象的屬性
    getName:function () { // 對象的方法
        console.log(this);// Object {name: "張三"}
    }
};
obj.getName();// 對象的方法調用
console.log(obj.name); // 張三
console.log(window.name);//

上述代碼先聲明一個對象名爲obj的對象,給對象添加屬性name,和方法getName,並在方法內部打印this的指向(對象自己:Object {name: "張三"}),調用對象的方法,打印this的指向是對象自己(Object {name: "張三"})而不是全局對象(window);

 

04、在事件處理中,其內部的this指向產生這個事件源的對象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id='btn'>click</button>
<script>
   var btn = document.getElementById('btn');// 獲取idbtn的標籤
   btn.onclick = function () {// 按鈕點擊事件
       console.log(this);

// <button id='btn'>click</button>
   };
</script>
</body>
</html>

上述代碼先用html建立一個按鈕,再給這個按鈕添加一個點擊事件,並打印this的指向(<button id =btn>click</button>),得出結論是this指向產生事件源的對象(<button id =btn>click</button>);

 

05、在定時器中其內部的this指針指向window對象

function Person() {
    // 備份指針
    console.log(this); // Person {}
    var self = this;
    setInterval(function () {
        console.log(self);// Person {}
        console.log(this);// Window
    }, 20);
}
new Person();

上述代碼先建立一個person函數,再用self來備份一下this指針,再建立定時器,定時器內部的this永遠指針指向window對象,有時候咱們咱們要用到指定的對象不是window對象,咱們能夠經過備份指針來實現;

 

06、經過call或者apply方式調用中(函數上下文),this指向的是當前的上下文,主要是改變this的指向

call方法: 傳入的參數數量不固定

第一個參數是要綁定給this的值(即函數體內this對象的指向)

第二個參數開始日後,每一個參數都依次的傳入做爲函數的參數

 

apply: 接收兩個參數

第一個參數是要綁定給this的值(即函數體內this對象的指向)

第二個就是一個參數數組

function Person() {
    this.name = 'Jack';
}
function Boy() {
    Person.call(this);
    console.log(this);// Boy {name: "Jack"}
}
var b1 = new Boy();

上述代碼建立兩個構造函數PersonBoy,使用call方法讓Person構造函數中的this指向Boy構造函數,至關於把Person構造函數內對象的屬性和方法深拷貝一份(包括引用類型:指針和堆空間的數據)

 

var obj = {
    name:"張三",
    getName:function (param1,param2) {
        console.log(this.name,param1,param2);
    }
}

obj.getName("123","456");      //張三 123 456

var obj2 = {name:"李四"};
obj.getName.call(obj2); //打印李四 undefined undefined

obj.getName.call(obj2,"測試字符串01","測試的字符串02"); // 李四 測試字符串01 測試的字符串02
obj.getName.apply(obj2,["123","456"]);   // 李四 123 456

上述代碼先建立一個對象obj並添加屬性name和方法getName,調用自身的方法得出的結果(張三 123 456),再建立一個對象obj2,添加屬性name,obj.getName.call(obj2);這句話的意思是obj的方法getName借給obj2使用,其obj方法內部的this指向obj2;得出的結果是李四 undefined(沒有傳參)  undefined(沒有傳參)call方法主要是改變this的指向;apply的方法做用和call同樣,只是傳的參數不同,call能夠只傳一個參數(要綁定給this的值),也能夠傳多個;而apply接收兩個參數(要綁定給this的值[],第二個參數是數組,數組的長度不定。

 

2、 this關鍵字用法的注意點

This的丟失問題

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="box"></div>
<script>
 var box = document.getElementById('box');// 獲取標籤
 var getId = document.getElementById;//
 var box = getId('box');// Uncaught TypeError: Illegal invocation (未捕獲的類型錯誤)
 console.log(box);
</script>
</body>
</html>

上述代碼先在html中建立一個idboxdiv,而後再js中獲取標籤,有時候咱們嫌獲取標籤的方法太長了,想要縮減一下(var getId = document.getElementById),再調用,然而上述代碼調用時則報錯了!緣由是方法內部的this指針丟失了,原先document.getElementById內部實現中用到this指針,其指向document對象,而getId調用時是按普通函數調用的,其內部的this指針指向window對象,因此執行到這一步的時候報錯!

 

如今用apply方法來修正this的指向

//借用apply來修正this
document.getElementById = (function (func) {
    return function () {
        return func.apply(document,arguments);
    }
})(document.getElementById);
var getId = document.getElementById;
/*上句代碼等同於下面這句代碼
var getId = function () {
    return document.getElementById.apply(document,arguments);
}*/
var box = getId('box');       //不會報錯
console.log(box);// <div id="box"></div>

上述代碼先在document.getElementById方法內部添加一個讓this指針一直指向document對象的操做;document.getElementById =(function(func){})(document.getElementById);這是一個當即執行函數,把document.getElementById看成實參傳進去,而函數內部則返回另外一個函數,而這個函數內部則執行改變this指向的操做document.getElementById.apply(document,arguments);意思是讓this永遠指向document對象;arguments指的是傳進去的實參Id(box);

 

3、結論

This關鍵字永遠指向實際調用者

 

4、源碼連接

https://github.com/350469960/OS/blob/master/javascript/this.md

相關文章
相關標籤/搜索