亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript中的this指向綁定規(guī)則及常見(jiàn)面試總結(jié)

 更新時(shí)間:2023年12月15日 09:24:58   作者:歸思君  
這篇文章主要為大家介紹了JavaScript中的this指向綁定規(guī)則及箭頭韓碩中的this指向,還b包含了常見(jiàn)面試總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、引言

this可以說(shuō)是前端開(kāi)發(fā)中比較常見(jiàn)的一個(gè)關(guān)鍵字,由于其指向是在運(yùn)行時(shí)才確定,所以大家在開(kāi)發(fā)中判斷其方向時(shí)也會(huì)很模糊,今天就把this的指向問(wèn)題拆開(kāi)了,揉碎了,好好講一講。

先來(lái)看一個(gè)場(chǎng)景,看看該處的 this 應(yīng)該指向哪:首先在 request.js 中定義一個(gè) getAction 函數(shù)

export function getAction(url,parameter) {
  let headers = {}
  if (this && this.realReferer && this.realReferer !== '') {
    headers.realReferer = window.location.origin + this.realReferer
  }
  return axios({
    url: url,
    method: 'get',
    params: parameter,
    headers
  });
}

然后在 test.vue 文件中引用該 getAction函數(shù)并使用

import { getAction } from '@api/request'
export default {
  methods: {
    getTableData() {
      getAction(this.url.requestUrl).then(res => {
        //1.這個(gè)時(shí)候getAction中的this將打印出什么
        //2.在該處打印this,會(huì)輸出什么
        console.log(this);
      })
    },
  }
}

現(xiàn)在有兩個(gè)問(wèn)題:

  • 在 test.vue中調(diào)用 getAction()時(shí),此時(shí)其內(nèi)部,也就是request.js 中的 this 指向什么?
  • 在 getAction() then 后的箭頭函數(shù)中的 this 指向什么?

思考一下能判斷出這兩個(gè)this的指向嗎?先賣(mài)個(gè)管子,等咱們?cè)僦v完this的相關(guān)原理后再來(lái)解答這兩個(gè)問(wèn)題。這篇文章會(huì)從這幾個(gè)方面講解:

  • 什么是this,this和執(zhí)行上下文的關(guān)系
  • this中的默認(rèn)、隱式、顯式和new的綁定規(guī)則

箭頭函數(shù)中的this指向問(wèn)題

二、什么是this?

this 其實(shí)就是一個(gè)JavaScript語(yǔ)言中的一個(gè)關(guān)鍵字,  它的值是某個(gè)對(duì)象引用值,其指代的是當(dāng)前執(zhí)行上下文中的對(duì)象。那么為何需要this?我們先來(lái)看看一個(gè)例子:

var testObj = {
  name: "testObj",
  print: function () {
      console.log(name)
  }
} 
var name = "global name";
//想通過(guò)調(diào)用print()來(lái)調(diào)用testObj中的name
testObj.print();//global name

從結(jié)果可知,最后print() 輸出"global name", 而不是 testObj 中的 name。為何出現(xiàn)這種情況?
這是因?yàn)?JavaScript 語(yǔ)言的作用域鏈?zhǔn)怯稍~法作用域決定的,而詞法作用域是由代碼結(jié)構(gòu)來(lái)確定的:

  • 當(dāng) testObj.print()執(zhí)行時(shí),這段代碼的詞法作用域是全局作用域,所以這個(gè)時(shí)候 js 引擎會(huì)去全局作用域中尋找 name,最后打印出“global name”。

因此為了避免這種情況,JavaScript 設(shè)計(jì)者引入了 this 機(jī)制,來(lái)調(diào)用對(duì)象的內(nèi)部屬性,如下代碼:

var testObj = {
  name: "testObj",
  print: function () {
      console.log(this.name)
  }
} 
var name = "global name";
testObj.print();//testObj

最后就能夠通過(guò)testObj.print() 來(lái)調(diào)用對(duì)象內(nèi)部的屬性了。
不同于詞法作用域鏈,this的指向是在運(yùn)行時(shí)才能確定,實(shí)際上當(dāng)執(zhí)行上下文創(chuàng)建后,會(huì)生成一個(gè)this引用值,指向當(dāng)前執(zhí)行上下文對(duì)象,如下圖所示:

而 js 引擎在執(zhí)行代碼時(shí)的運(yùn)行時(shí)上下文主要有三種:全局執(zhí)行上下文、函數(shù)執(zhí)行上下文和 eval 執(zhí)行上下文。不同場(chǎng)景的this指向如下:

//全局執(zhí)行上下文,當(dāng)前對(duì)象是window
console.log(this);//window
//函數(shù)執(zhí)行上下文外部對(duì)象是全局對(duì)象,所以指向全局對(duì)象window
function test(){
console.log(this);//window
}
//函數(shù)執(zhí)行上下文外部對(duì)象是test,因此指向當(dāng)前的對(duì)象test
var test = {
test: function(){
  console.log(this);//test{...}對(duì)象
}
}
//eval執(zhí)行上下文,根據(jù)默認(rèn)綁定規(guī)則,指向全局對(duì)象window
eval(`console.log(this); `) //window

正是因?yàn)閠his在運(yùn)行中才得以確定其指向的上下文對(duì)象,所以為了規(guī)范和標(biāo)準(zhǔn)化this的指向方式,規(guī)定了一系列的綁定規(guī)則,來(lái)決定什么情況下this會(huì)綁定到哪個(gè)對(duì)象。下面就來(lái)聊聊this的綁定規(guī)則

三、this 綁定規(guī)則

this的綁定大致可以劃分為默認(rèn)、隱式、顯式和new四種場(chǎng)景下的綁定規(guī)則:

1. 默認(rèn)綁定

當(dāng)函數(shù)被獨(dú)立調(diào)用時(shí),會(huì)將this綁定到全局對(duì)象。瀏覽器環(huán)境下是window, 嚴(yán)格模式是undefined主要有以下幾種場(chǎng)景:

//1. 定義在全局對(duì)象下的函數(shù)被獨(dú)立調(diào)用
function test(){
  console.log("global:", this);
}
test();//window
//2. 定義在某個(gè)對(duì)象下的函數(shù)被獨(dú)立調(diào)用
var testObj = {
test: function(){
  console.log("testObj:", this);
}
}
var testfun = testObj.test;
testfun();//window
//3. 定義在某個(gè)函數(shù)下的函數(shù)被獨(dú)立調(diào)用
function testFun(fn){
  fn();
}
testFun(testObj.test); //window

2. 隱式綁定

當(dāng)函數(shù)作為對(duì)象的方法被調(diào)用時(shí),隱式綁定規(guī)則會(huì)將this綁定到調(diào)用該方法的對(duì)象,也就是"誰(shuí)調(diào)用,就指向誰(shuí)"。

const obj = {
name: 'innerObj',
fn:function(){
  return this.name;
}
}
//調(diào)用者是obj, this指向obj
console.log(obj.fn());//innerObj

const obj2 = {
name: 'innerObj2',
fn: function() {
  return obj.fn(); //此時(shí)是obj調(diào)用fn,所以此時(shí)this指向obj
}
}
//調(diào)用者是obj, this指向obj
console.log(obj2.fn())//innerObj

現(xiàn)在我們可以回答引言中的問(wèn)題1:在request.js 的getAction() 中this指向test.vue 中的全局vue對(duì)象,因?yàn)?code>import {getAction} from '@api/request' 后,相當(dāng)于vue對(duì)象調(diào)用了getAction(),因此其內(nèi)部的this方向符合隱式綁定規(guī)則,所以指向調(diào)用者——test.vue 中的全局vue對(duì)象

3. 顯式綁定

顯式綁定主要指通過(guò)call、apply和bind方法可以顯式地綁定this的值:

call 方法

語(yǔ)法: function.call(thisArg, arg1, arg2, ...) :

參數(shù): thisArg 表示 this 指向的上下文對(duì)象, arg1...argn  表示一系列參數(shù)

功能:  無(wú)返回值立即調(diào)用 function 函數(shù)

var test = {
}
function test2(){
  console.log(this);
}
//此時(shí)是獨(dú)立函數(shù),因此指向全局對(duì)象
test2();//window
//call顯式綁定,將函數(shù)內(nèi)部的this綁定至call中指定的引用對(duì)象
test2.call(test);//test

apply 方法

語(yǔ)法: function.apply(thisArg, [argsArray]) :

參數(shù): thisArg 表示 this 指向的上下文對(duì)象, argsArray  表示參數(shù)數(shù)組

功能: 沒(méi)有返回值, 立即調(diào)用函數(shù)

apply 和 call 的區(qū)別在于傳參,call 傳的是一系列參數(shù),apply 傳的是參數(shù)數(shù)組

var test = {
}
function test2(name){
  console.log(this);
  console.log(name);
}
//此時(shí)是獨(dú)立函數(shù),因此指向全局對(duì)象
test2();//window
//call顯式綁定,將函數(shù)內(nèi)部的this綁定至call中指定的引用對(duì)象
test2.apply(test, ["name"]);//test, name
test2.call(test, "name"); //test

bind 方法

語(yǔ)法:function.bind(thisArg[, arg1[, arg2[, ...]]])

參數(shù): thisArg 表示 this 指向的上下文對(duì)象; arg1, arg2, ...表示 要傳遞給函數(shù)的參數(shù)。這些參數(shù)將按照順序傳遞給函數(shù),并在調(diào)用函數(shù)時(shí)作為函數(shù)參數(shù)使用

功能: 返回原函數(shù) function 的拷貝, 這個(gè)拷貝的 this 指向 thisArg

var test = {
  fun: function(){
      console.log(this);
      var test = function(){
          console.log("test", this);
      }
      //1. 因?yàn)閠est.fun()在全局作用域中,所以屬于獨(dú)立函數(shù)調(diào)用,默認(rèn)綁定規(guī)則指向全局對(duì)象
      test(); //window
      //2. bind方法會(huì)創(chuàng)建一個(gè)原函數(shù)的拷貝,并將拷貝中的this指向bind參數(shù)中的上下文對(duì)象
      var test2 = test.bind(this);
      test2();//test
      //3. apply方法會(huì)將this指向參數(shù)中的上下文,并立即執(zhí)行函數(shù)
      test.apply(this);//test
      
  }
}
test.fun();

4. new 綁定

主要是在使用構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),new 綁定規(guī)則會(huì)將 this 綁定到新創(chuàng)建的實(shí)例對(duì)象,因此構(gòu)造函數(shù)中用 this 指向的屬性值和參數(shù)也會(huì)被賦給實(shí)例對(duì)象:

function funtest(){
  this.name = "funtest"
}
var tete = new funtest();
console.log(tete.name); //"funtest"

new 操作符實(shí)際上的操作步驟:

  • 創(chuàng)建一個(gè)新的對(duì)象 {}
  • 將構(gòu)造函數(shù)中的 this 指向這個(gè)新創(chuàng)建的對(duì)象
  • 為這個(gè)新對(duì)象添加屬性、方法等
  • 返回這個(gè)新對(duì)象

等價(jià)于如下代碼:

var obj = {}
obj._proto_ = funtest.prototype
funtest.call(obj)

5. 綁定規(guī)則的優(yōu)先級(jí)

上述的綁定規(guī)則有時(shí)會(huì)一起出現(xiàn),因此需要判斷不同規(guī)則之間的優(yōu)先級(jí),然后再來(lái)確定其 this 指向:
a. 首先是默認(rèn)綁定和隱式綁定,執(zhí)行以下代碼:

function testFun(){
    console.log(this);
}
var testobj = {
    name:"testobj",
    fun:testFun
}
//若輸出window,則證明優(yōu)先級(jí)默認(rèn)綁定大于隱式綁定;
//若輸出testobj,則證明優(yōu)先級(jí)隱式綁定大于默認(rèn)綁定;
testobj.fun()//testobj

輸出為 testobj 對(duì)象,所以隱式綁定的優(yōu)先級(jí)高于默認(rèn)綁定b. 下面來(lái)看一下隱式綁定和顯式綁定,執(zhí)行以下代碼:

function testFun(){
    console.log(this);
}
var testobj = {
    name:"testobj",
    fun:testFun
}
//若輸出testobj,則證明優(yōu)先級(jí)隱式綁定大于顯式綁定
//若輸出{}, 則證明優(yōu)先級(jí)顯式綁定大于隱式綁定
testobj.fun.call({})//{}

結(jié)果輸出 { },說(shuō)明顯式綁定優(yōu)先級(jí)大于隱式綁定c. 顯式綁定的 call, apply,bind 的優(yōu)先級(jí)相同,與先后順序有關(guān),看以下代碼:

function testFun(){
    console.log(this);
}
var testobj = {
    name:"testobj",
    fun:testFun
}
//若輸出testobj,則證明優(yōu)先級(jí)隱式綁定大于顯式綁定
//若輸出{}, 則證明優(yōu)先級(jí)顯式綁定大于隱式綁定
testobj.fun.call({})//{}
testobj.fun.call(testobj)

d. 最后來(lái)看看顯式綁定和 new 綁定的優(yōu)先級(jí),執(zhí)行以下代碼:

function testFun(){
    console.log(this.name);
}
var testobj = {
    name:"testobj",
}
testFun.call(testobj);//testobj
//new 操作符創(chuàng)建了一個(gè)新的對(duì)象,并將this重新指向新對(duì)象
//覆蓋了testFun原來(lái)綁定的testobj對(duì)象
var instance = new testFun();
console.log(instance.name) //undefined

從結(jié)果可知,new 綁定的優(yōu)先級(jí)大于顯式綁定

最后總結(jié)一下 this 綁定的 優(yōu)先級(jí)是:

fn()(全局環(huán)境)(默認(rèn)綁定)< obj.fn()(隱式綁定) < fn.call(obj)=fn.apply(obj) = fn.bind(obj)(顯式綁定)< new fn()

6. 綁定的丟失

有時(shí) this 綁定可能會(huì)在某些情況下丟失,導(dǎo)致 this 值的指向變得不確定:

賦值給變量后調(diào)用

當(dāng)使用一個(gè)變量作為函數(shù)的引用值,并使用變量名執(zhí)行函數(shù)時(shí),會(huì)發(fā)生綁定丟失,此時(shí) this 會(huì)默認(rèn)綁定到全局對(duì)象或變成 undefined(嚴(yán)格模式下)

var lostObj = {
  name: "lostObj",
  fun: function(){
    console.log(this);
    }
}
var lostfun = lostObj.fun;
lostfun();//window
lostObj.fun();//lostObj

從結(jié)果發(fā)現(xiàn),lostfun 雖然指向?qū)ο笾械姆椒ǎ窃谡{(diào)用時(shí)發(fā)生了 this 綁定丟失。因?yàn)楫?dāng)賦值給變量時(shí),對(duì)象中的 fun就失去了與對(duì)象的關(guān)聯(lián),變成了一個(gè)獨(dú)立函數(shù),所以此時(shí)執(zhí)行 lostfun也就相當(dāng)于執(zhí)行獨(dú)立函數(shù),默認(rèn)綁定到全局對(duì)象。
那如果通過(guò)對(duì)象來(lái)執(zhí)行呢?看如下代碼:

var lostObj = {
  name: "lostObj",
  fun: function(){
    console.log(this);
    }
}
var lostObj2 = {
  name: "lostObj2",
  fun: lostObj.fun
}
var lostfun = lostObj.fun;
lostfun();//window
lostObj.fun();//lostObj
lostObj2.fun();//lostObj2

同樣,一旦將方法賦值給變量后,其內(nèi)部與對(duì)象的關(guān)聯(lián)就此丟失,默認(rèn)綁定到全局對(duì)象。但是將變量放到對(duì)象中后,就與該對(duì)象進(jìn)行關(guān)聯(lián)。所以該方法執(zhí)行后的 this 執(zhí)行了 lostObj2對(duì)象。

函數(shù)作為參數(shù)傳遞

將函數(shù)作為參數(shù)傳遞到新函數(shù)中,并在新函數(shù)中執(zhí)行該參數(shù)函數(shù):

var lostObj3 = {
  name: "lostObj3",
  fun: function(){
    console.log(this.name);
    }
}
var name = "global"
function doFun(fn){
  fn();
}
doFun(lostObj3.fun);//global

從結(jié)果可知,當(dāng)函數(shù)作為參數(shù)傳遞后,其形參 fn 被賦值為 lostObj3.fun。實(shí)際上也相當(dāng)于賦值給變量后調(diào)用這種情況,而且 doFun()作為獨(dú)立函數(shù)調(diào)用,所以其 this 也就指向全局對(duì)象了

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

如果將對(duì)象方法作為回調(diào)函數(shù)傳遞給其他函數(shù),this 綁定也可能丟失

var lostObj4 = {
  name: 'lostObj4',
  fun: function() {
    setTimeout(function() {
      console.log(`Hello, ${this.name}!`);
    });
  }
};
lostObj4.fun(); // Hello, undefined!

因?yàn)?nbsp;setTimeout 的回調(diào)函數(shù)最后會(huì)以普通函數(shù)的形式調(diào)用,所以其 this 指向的是全局對(duì)象,所以即便是 lostObj4調(diào)用 fun(),最后其內(nèi)部的 this 仍然會(huì)丟失。

嵌套函數(shù)

當(dāng)某個(gè)函數(shù)是嵌套在另一個(gè)函數(shù)內(nèi)部的函數(shù)時(shí),內(nèi)部函數(shù)中的 this 綁定會(huì)丟失,并且會(huì)綁定到全局對(duì)象或 undefined(嚴(yán)格模式下):

var lostObj5 = {
  name: 'lostObj5',
  fun: function() {
    function innerFun() {
      console.log(`Hello, ${this.name}!`);
    };
    innerFun();
  }
};
lostObj5.fun();// Hello, undefined!

從結(jié)果可以發(fā)現(xiàn),嵌套函數(shù) innerFun()中的 this 此時(shí)是指向全局環(huán)境。所以從這個(gè)案例可以說(shuō)明作用域鏈和 this 沒(méi)有關(guān)系,作用域鏈不影響 this 的綁定。

原因是當(dāng)innerFun()被調(diào)用時(shí),是作為普通函數(shù)調(diào)用,不像 fun()屬于對(duì)象 lostObj5的內(nèi)部方法而調(diào)用,因此最后其內(nèi)部的 this 指向全局對(duì)象。

其實(shí) this 丟失可以通過(guò)箭頭函數(shù)來(lái)解決,下面就來(lái)聊聊箭頭函數(shù)

四、箭頭函數(shù)中的 this

箭頭函數(shù)是 ES6 增加的一種編寫(xiě)函數(shù)的方法,它用簡(jiǎn)潔的方式來(lái)表達(dá)函數(shù)
語(yǔ)法:()=>{}
參數(shù):(): 函數(shù)的參數(shù),{}: 函數(shù)的執(zhí)行體

1. 箭頭函數(shù)中的 this 指向

箭頭函數(shù)中的this是在定義時(shí)確定的,它是繼承自外層詞法作用域。而不是在運(yùn)行時(shí)才確定,如以下代碼:

var testObj2 = {
    name: "testObj2", 
    fun: function(){
        setTimeout(()=>{
            console.log(this);
        })
    }
}
var testObj3 = {
    name: "testObj3", 
    fun: function(){
        setTimeout(function(){
            console.log(this);
        })
    }
}
//即使獨(dú)立調(diào)用函數(shù),箭頭函數(shù)內(nèi)的this指向是在定義時(shí)就已經(jīng)確定
testObj2.fun();//testObj
testObj3.fun();//window

實(shí)際上箭頭函數(shù)中沒(méi)有 this 綁定,它是繼承自外層作用域的 this 值。因此在許多情況下,箭頭函數(shù)能解決 this 在運(yùn)行時(shí)函數(shù)的綁定問(wèn)題。

2. 箭頭函數(shù)與普通函數(shù)中的 this 差異

從 上面的例子可以看出箭頭函數(shù)和普通函數(shù)在 this 的處理上存在很大的差異,主要有:

this 綁定方式

普通函數(shù)的 this 是在運(yùn)行時(shí)確定的;箭頭函數(shù)的 this 值是函數(shù)定義好后就已經(jīng)確定,它繼承自包含箭頭函數(shù)的外層作用域

作用域

普通函數(shù)是具有動(dòng)態(tài)作用域,其 this 值在運(yùn)行時(shí)基于函數(shù)的調(diào)用方式動(dòng)態(tài)確定。箭頭函數(shù)具有詞法作用域,其 this 值在定義時(shí)就已經(jīng)確定,并繼承外部作用域

綁定 this 的對(duì)象

普通函數(shù)中 this 可以通過(guò)函數(shù)的調(diào)用方式(如對(duì)象方法、構(gòu)造函數(shù)、函數(shù)調(diào)用等)來(lái)綁定到不同的對(duì)象,而箭頭函數(shù)沒(méi)有自己的 this 綁定;箭頭函數(shù)沒(méi)有自己的 this 綁定,它只能繼承外部作用域的 this 值,無(wú)法在運(yùn)行時(shí)改變綁定對(duì)象,而且也無(wú)法通過(guò)顯式綁定來(lái)改變 this 的指向。

var testObj4 = {
  arrowFun: ()=>{
    console.log(this);
  },
  normalFun: function(){
    console.log(this);
  }
}
//此時(shí)箭頭函數(shù)的this繼承全局上下文的this,顯式綁定無(wú)法修改箭頭函數(shù)中的this值
testObj4.arrowFun();//window
testObj4.arrowFun.apply({});//window
testObj4.normalFun();//testObj4
testObj4.normalFun.apply({});//{}

下面我們就可以解答引言中的問(wèn)題 2 了。箭頭函數(shù)中的 this 指向其上層的作用域,也就是 getAction() 中的 this 值,而從隱式綁定調(diào)用規(guī)則,當(dāng)前是 vue 實(shí)例調(diào)用 getTableData()然后再調(diào)用 getAction(),因此 this 值指向當(dāng)前 vue 實(shí)例。

五、 this 中的面試題

手寫(xiě)實(shí)現(xiàn)一個(gè) bind 函數(shù)

通過(guò)分析 bind 函數(shù)的語(yǔ)法和參數(shù)來(lái):function.bind(thisArg[, arg1[, arg2[, ...]]])

  • 返回值是一個(gè)函數(shù)
  • 參數(shù) thisArg 指向

我們暫時(shí)不考慮原型問(wèn)題,實(shí)現(xiàn)如下代碼:

Function.prototype.mybind = function (thisArg) {
  //1.隱式綁定,當(dāng)前的this指向目標(biāo)函數(shù)
  var targetFn = this;
  //將參數(shù)列表轉(zhuǎn)換為數(shù)組,并刪除第一個(gè)參數(shù)
  var args = Array.prototype.slice.call(arguments, 1);
  //2.返回值一個(gè)函數(shù)
  return function bound() {
     var innerArgs = Array.prototype.slice.call(arguments);
     var finalArgs = args.concat(innerArgs);
    //解決返回函數(shù)使用new后,綁定this忽略問(wèn)題
     var _this = targetFn instanceof this ? this: thisArg;
     return targetFn.apply(thisArg, finalArgs)
   }
 }
}

總結(jié)

文章回顧 this 的概念和 this 指向的判斷綁定規(guī)則,

  • 首先是綁定規(guī)則:
  • 獨(dú)立函數(shù)調(diào)用執(zhí)行時(shí),使用默認(rèn)綁定規(guī)則,this 指向 window
  • 當(dāng)函數(shù)作為對(duì)象方法被調(diào)用,使用隱式綁定規(guī)則,this 指向這個(gè)對(duì)象
  • 當(dāng)函數(shù)作為構(gòu)造方法時(shí),使用 new 綁定規(guī)則,this 指向返回的對(duì)象
  • apply/call/bind 要注意參數(shù)的傳遞和返回值不同
  • 箭頭函數(shù)要看該箭頭函數(shù)在哪個(gè)作用域下,this 就指向誰(shuí)

綁定規(guī)則的優(yōu)先級(jí):

fn()(全局環(huán)境)(默認(rèn)綁定)< obj.fn()(隱式綁定) < fn.call(obj)=fn.apply(obj) = fn.bind(obj)(顯式綁定)< new fn()

  • 此外要注意綁定失效的情況,善用箭頭函數(shù)來(lái)保證 this 的指向穩(wěn)定

以上就是JavaScript中的this指向綁定規(guī)則及常見(jiàn)面試總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript this指向的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論