成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入理解 Javascript 之 this

OnlyMyRailgun / 3205人閱讀

摘要:深入淺出的理解問題的由來寫法一寫法二雖然和指向同一個(gè)函數(shù),但是執(zhí)行結(jié)果可能不一樣。該變量由運(yùn)行環(huán)境提供。所以,就出現(xiàn)了,它的設(shè)計(jì)目的就是在函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運(yùn)行環(huán)境。

深入淺出this的理解 問題的由來
var obj = {
    foo: function(){}
}

var foo = obj.foo;

// 寫法一
obj.foo();

// 寫法二
foo();

雖然obj.foo和foo指向同一個(gè)函數(shù),但是執(zhí)行結(jié)果可能不一樣。

var obj = {
    foo: function() {
        conosle.log(this.bar)
    },
    bar: 2
};

var foo = obj.foo;
var bar = 3;

obj.foo(); // 2
foo(); // 3

這種差異的原因就是因?yàn)閮?nèi)部使用了this關(guān)鍵字,this指向的是函數(shù)運(yùn)行的所在環(huán)境,對(duì)于obj.foo()來說,this執(zhí)行obj,對(duì)于foo()來說,this指向window全局環(huán)境

this的原理 內(nèi)存的數(shù)據(jù)結(jié)構(gòu)

JavaScript 語言之所以有this的設(shè)計(jì),跟內(nèi)存里面的數(shù)據(jù)結(jié)構(gòu)有關(guān)系。

var obj = {foo: 5}

也就是或變量obj是一個(gè)地址,后面讀取obj.foo引擎先從obj拿到地址,然后再從該地址讀取原始對(duì)象,返回它的屬性值。

原始的對(duì)象以字典結(jié)構(gòu)保存,每一個(gè)屬性名都對(duì)應(yīng)一個(gè)屬性描述對(duì)象。舉例來說,上面例子的foo屬性,實(shí)際上是以下面的形式保存的。

函數(shù)

這樣的結(jié)構(gòu)是很清晰的,問題在于屬性的值可能是一個(gè)函數(shù)。

var obj = { foo: function () {} };

這時(shí),引擎會(huì)將函數(shù)多帶帶保存在內(nèi)存中,然后再將函數(shù)的地址賦值給foo屬性的value屬性。

由于函數(shù)是一個(gè)多帶帶的值,所以它可以在不同的環(huán)境(上下文)執(zhí)行。

var f = function () {};
var obj = { f: f };

// 多帶帶執(zhí)行
f()

// obj 環(huán)境執(zhí)行
obj.f()
環(huán)境變量
var f = function () {
  console.log(x);
};

上面代碼中,函數(shù)體里面使用了變量x。該變量由運(yùn)行環(huán)境提供。

現(xiàn)在問題就來了,由于函數(shù)可以在不同的運(yùn)行環(huán)境執(zhí)行,所以需要有一種機(jī)制,能夠在函數(shù)體內(nèi)部獲得當(dāng)前的運(yùn)行環(huán)境(context)。所以,this就出現(xiàn)了,它的設(shè)計(jì)目的就是在函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運(yùn)行環(huán)境。

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

var x = 1;
var obj = {
  f: f,
  x: 2,
};

// 多帶帶執(zhí)行
f() // 1

// obj 環(huán)境執(zhí)行
obj.f() // 2

在obj環(huán)境執(zhí)行,this.x指向obj.x。
函數(shù)f在全局環(huán)境執(zhí)行,this.x指向全局環(huán)境的x。

回到我們最初的問題 obj.foo()是通過obj找到foo,所以就是在obj環(huán)境執(zhí)行。一旦var foo = obj.foo,變量foo就直接指向函數(shù)本身,所以foo()就變成在全局環(huán)境執(zhí)行。

阮一峰老師的 this原理

繼續(xù)我們的this

this在js中一直是謎一樣的存在著,在面試中也是經(jīng)常會(huì)被問道

this的指向在函數(shù)創(chuàng)建的時(shí)候是決定不了的,在調(diào)用的時(shí)候才能決定

全局范圍內(nèi)

this;    //在全局范圍內(nèi)使用`this`,它將會(huì)指向全局對(duì)象

var name="zhoulujun";

function say(){
    console.log(this.name)
}
say(); //zhoulujun

當(dāng)執(zhí)行 say函數(shù)的時(shí)候, JavaScript 會(huì)創(chuàng)建一個(gè) Execute context (執(zhí)行上下文),執(zhí)行上下文中就包含了 say函數(shù)運(yùn)行期所需要的所有信息。 Execute context 也有自己的 Scope chain, 當(dāng)函數(shù)運(yùn)行時(shí), JavaScript 引擎會(huì)首先從用 say函數(shù)的作用域鏈來初始化執(zhí)行上下文的作用域鏈。

函數(shù)調(diào)用

foo();    //this指向全局對(duì)象

方法調(diào)用*

test.foo();    //this指向test對(duì)象

調(diào)用構(gòu)造函數(shù)*

new foo();    //函數(shù)與new一塊使用即構(gòu)造函數(shù),this指向新創(chuàng)建的對(duì)象

顯式的設(shè)置this*

function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]);    //this被設(shè)置成bar
foo.call(bar, 1, 2, 3);       //this被設(shè)置成bar
從函數(shù)調(diào)用理解this

實(shí)例1

myObj3={
        site:"zhoulujun.cn",
        andy:{
            site:"www.zhoulujun.cn",
            fn:function(){
                console.log(this)
                console.log(this.site)
            }
        }
    };
var site="111";
var fn=myObj3.andy.fn;
fn();  // 這里的調(diào)用環(huán)境是window


// Window?{postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window,?…}
// 111

實(shí)例2

如果一個(gè)函數(shù)中有this,這個(gè)函數(shù)中包含多個(gè)對(duì)象,盡管這個(gè)函數(shù)是被最外層的對(duì)象所調(diào)用,this指向的也只是它上一級(jí)的對(duì)象

myObj3={
    site:"zhoulujun.cn",
    andy:{
        site:"www.zhoulujun.cn",
        fn:function(){
            console.log(this)
            console.log(this.site)
        }
    }
};
var site="111";
myObj3.andy.fn();


VM51:6 {site: "www.zhoulujun.cn", fn: ?}
VM51:7 www.zhoulujun.cn

實(shí)例3

document.getElementById( "div1" ).onclick = function(){
    console.log( this.id );// 輸出: div1
    var func = function(){ 
        console.log ( this.id );// 輸出: undefined
    } 
    func();
}; 
//修正后
document.getElementById( "div1" ).onclick = function(){
    var func = function(){ 
        console.log ( this.id );// 輸出: div1
    } 
    func.call(this);
}; 

實(shí)例4

var A = function( name ){ 
    this.name = name;
};
var B = function(){ 
    A.apply(this,arguments);
};
B.prototype.getName = function(){ 
    return this.name;
};
var b=new B("sven");
console.log( b.getName() ); // 輸出:  "sven"

實(shí)例5

function foo() {
    console.log( this.a );
}

var obj1 = {
    a: 2,
    foo: foo
};

var obj2 = {
    a: 3,
    foo: foo
};

obj1.foo(); // 2
obj2.foo(); // 3

obj1.foo.call( obj2 ); // 3
obj2.foo.call( obj1 ); // 2
apply、call

因?yàn)閍pply、call存在于Function.prototype中,所以每個(gè)方法都有這兩個(gè)屬性。

call
函數(shù)名.call(對(duì)象,arg1....argn)
//功能:
    //1.調(diào)用函數(shù)
    //2.將函數(shù)內(nèi)部的this指向第一個(gè)參數(shù)的對(duì)象
    //3.將第二個(gè)及以后所有的參數(shù),作為實(shí)參傳遞給函數(shù)
apply主要用途是直接用數(shù)組傳參
函數(shù)名.apply(對(duì)象, 數(shù)組/偽數(shù)組);
//功能:
    //1.調(diào)用函數(shù)
    //2.將函數(shù)內(nèi)部的this指向第一個(gè)參數(shù)的對(duì)象
    //3.將第二個(gè)參數(shù)中的數(shù)組(偽數(shù)組)中的元素,拆解開依次的傳遞給函數(shù)作為實(shí)參
//案例求數(shù)組中最大值
var a=Math.max.apply( null, [ 1, 2, 5, 3, 4 ] );
console.log(a);// 輸出:5

call應(yīng)用(將偽數(shù)組轉(zhuǎn)為數(shù)組)

var arrayLike = {0: "name", 1: "age", 2: "sex", length: 3 }
Array.prototype.join.call(arrayLike, "&"); // name&age&sex
Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"] 
// slice可以做到類數(shù)組轉(zhuǎn)數(shù)組
Array.prototype.map.call(arrayLike, function(item){
    return item.toUpperCase();
}); 
// ["NAME", "AGE", "SEX"]


console.log(
    Object.prototype.toString.call(num),
    Object.prototype.toString.call(str),
    Object.prototype.toString.call(bool),
    Object.prototype.toString.call(arr),
    Object.prototype.toString.call(json),
    Object.prototype.toString.call(func),
    Object.prototype.toString.call(und),
    Object.prototype.toString.call(nul),
    Object.prototype.toString.call(date),
    Object.prototype.toString.call(reg),
    Object.prototype.toString.call(error)
);
// "[object Number]" "[object String]" "[object Boolean]" "[object Array]" "[object Object]"
// "[object Function]" "[object Undefined]" "[object Null]" "[object Date]" "[object RegExp]" "[object Error]"

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96796.html

相關(guān)文章

  • 深入理解 Javascript 繼承

    摘要:繼承繼承子類可以使用父類的所有功能,并且對(duì)這些功能進(jìn)行擴(kuò)展。類繼承父類父類添加共有方法子類繼承父類子類添加共有方法其中最核心的一句代碼是將原型指向了父類的原型對(duì)象。 繼承 繼承:子類可以使用父類的所有功能,并且對(duì)這些功能進(jìn)行擴(kuò)展。繼承的過程,就是從一般到特殊的過程。 類繼承 // 父類 var supperClass = function() { var id = 1; thi...

    wuyangnju 評(píng)論0 收藏0
  • 深入理解 Javascript JS的封裝

    摘要:封裝常見的封裝類中的共有和私有執(zhí)行結(jié)果如下原因是調(diào)用的時(shí)候,指向的其實(shí)是,因此沒有輸出解決辦法更改指向工廠函數(shù)也有對(duì)于程序員來說這三個(gè)關(guān)鍵字應(yīng)該是很熟悉的哈,但是在中,并沒有類似于這樣的關(guān)鍵字,但是我們又希望我們定義的屬性和方法有一定的訪問 封裝 常見的封裝 function Person (name,age,sex){ this.name = name; this.a...

    張漢慶 評(píng)論0 收藏0
  • JavaScript深入淺出

    摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點(diǎn)提及,但是只要善于運(yùn)用,其實(shí)基于原型的繼承模型比傳統(tǒng)的類繼承還要強(qiáng)大。中文指南基本操作指南二繼續(xù)熟悉的幾對(duì)方法,包括,,。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。 怎樣使用 this 因?yàn)楸救藢儆趥吻岸?,因此文中只看懂?8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...

    blair 評(píng)論0 收藏0
  • 【進(jìn)階2-2期】JavaScript深入從作用域鏈理解閉包

    摘要:使用上一篇文章的例子來說明下自由變量進(jìn)階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數(shù),也不是局部變量,所以是自由變量。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第7天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)...

    simpleapples 評(píng)論0 收藏0
  • 深入理解JavaScript系列6:S.O.L.I.D五大原則單一職責(zé)

    摘要:,開始我們的第一篇單一職責(zé)。通過解耦可以讓每個(gè)職責(zé)工更加有彈性地變化。關(guān)于本文本文轉(zhuǎn)自大叔的深入理解系列。深入理解系列文章,包括了原創(chuàng),翻譯,轉(zhuǎn)載,整理等各類型文章,原文是大叔的一個(gè)非常不錯(cuò)的專題,現(xiàn)將其重新整理發(fā)布。 前言 Bob大叔提出并發(fā)揚(yáng)了S.O.L.I.D五大原則,用來更好地進(jìn)行面向?qū)ο缶幊蹋宕笤瓌t分別是: The Single Responsibility Princi...

    walterrwu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<