最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

一、引言

this可以說是前端開發(fā)中比較常見的一個關鍵字,由于其指向是在運行時才確定,所以大家在開發(fā)中判斷其方向時也會很模糊,今天就把this的指向問題拆開了,揉碎了,好好講一講。

先來看一個場景,看看該處的 this 應該指向哪:首先在 request.js 中定義一個 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.這個時候getAction中的this將打印出什么
        //2.在該處打印this,會輸出什么
        console.log(this);
      })
    },
  }
}

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

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

思考一下能判斷出這兩個this的指向嗎?先賣個管子,等咱們再講完this的相關原理后再來解答這兩個問題。這篇文章會從這幾個方面講解:

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

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

二、什么是this?

this 其實就是一個JavaScript語言中的一個關鍵字,  它的值是某個對象引用值,其指代的是當前執(zhí)行上下文中的對象。那么為何需要this?我們先來看看一個例子:

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

從結果可知,最后print() 輸出"global name", 而不是 testObj 中的 name。為何出現(xiàn)這種情況?
這是因為 JavaScript 語言的作用域鏈是由詞法作用域決定的,而詞法作用域是由代碼結構來確定的:

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

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

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

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

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

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

正是因為this在運行中才得以確定其指向的上下文對象,所以為了規(guī)范和標準化this的指向方式,規(guī)定了一系列的綁定規(guī)則,來決定什么情況下this會綁定到哪個對象。下面就來聊聊this的綁定規(guī)則

三、this 綁定規(guī)則

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

1. 默認綁定

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

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

2. 隱式綁定

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

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(); //此時是obj調(diào)用fn,所以此時this指向obj
}
}
//調(diào)用者是obj, this指向obj
console.log(obj2.fn())//innerObj

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

3. 顯式綁定

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

call 方法

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

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

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

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

apply 方法

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

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

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

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

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

bind 方法

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

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

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

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

4. new 綁定

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

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

new 操作符實際上的操作步驟:

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

等價于如下代碼:

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

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

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

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

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

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

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

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

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

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

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

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

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

6. 綁定的丟失

有時 this 綁定可能會在某些情況下丟失,導致 this 值的指向變得不確定:

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

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

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

從結果發(fā)現(xiàn),lostfun 雖然指向?qū)ο笾械姆椒ǎ窃谡{(diào)用時發(fā)生了 this 綁定丟失。因為當賦值給變量時,對象中的 fun就失去了與對象的關聯(lián),變成了一個獨立函數(shù),所以此時執(zhí)行 lostfun也就相當于執(zhí)行獨立函數(shù),默認綁定到全局對象。
那如果通過對象來執(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)部與對象的關聯(lián)就此丟失,默認綁定到全局對象。但是將變量放到對象中后,就與該對象進行關聯(lián)。所以該方法執(zhí)行后的 this 執(zhí)行了 lostObj2對象。

函數(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

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

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

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

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

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

嵌套函數(shù)

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

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

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

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

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

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

箭頭函數(shù)是 ES6 增加的一種編寫函數(shù)的方法,它用簡潔的方式來表達函數(shù)
語法:()=>{}
參數(shù):(): 函數(shù)的參數(shù),{}: 函數(shù)的執(zhí)行體

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

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

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

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

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

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

this 綁定方式

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

作用域

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

綁定 this 的對象

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

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

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

五、 this 中的面試題

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

通過分析 bind 函數(shù)的語法和參數(shù)來:function.bind(thisArg[, arg1[, arg2[, ...]]])

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

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

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

總結

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

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

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

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

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

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

相關文章

  • 使用babylon.js導入導出模型

    使用babylon.js導入導出模型

    Babylon.js是一個開源的3D圖形引擎,支持導入和渲染多種3D模型格式,如.obj、.gltf、.fbx等,通過使用SceneLoader或特定格式的加載器(如GLTFLoader或FBXLoader),可以輕松導入模型,雖然Babylon.js不直接支持導出模型
    2024-11-11
  • 利用js+canvas實現(xiàn)掃雷游戲

    利用js+canvas實現(xiàn)掃雷游戲

    這篇文章主要為大家詳細介紹了利用js+canvas實現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Js實現(xiàn)雙擊鼠標自動滾動屏幕的示例代碼

    Js實現(xiàn)雙擊鼠標自動滾動屏幕的示例代碼

    這篇文章主要介紹了Js實現(xiàn)雙擊鼠標自動滾動屏幕的示例代碼。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12
  • Android 自定義view仿微信相機單擊拍照長按錄視頻按鈕

    Android 自定義view仿微信相機單擊拍照長按錄視頻按鈕

    這篇文章主要介紹了Android 自定義view仿微信相機單擊拍照長按錄視頻按鈕,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-07-07
  • ES6 如何改變JS內(nèi)置行為的代理與反射

    ES6 如何改變JS內(nèi)置行為的代理與反射

    這篇文章主要介紹了ES6 如何改變JS內(nèi)置行為的代理與反射,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • JavaScript中l(wèi)ayer關閉指定彈出窗口方法總結

    JavaScript中l(wèi)ayer關閉指定彈出窗口方法總結

    這篇文章主要給大家介紹了關于JavaScript中l(wèi)ayer關閉指定彈出窗口方法的相關資料,layer是layui的一個彈出層組件,但是可以作為獨立組件使用,需要的朋友可以參考下
    2023-10-10
  • JavaScript使用focus()設置焦點失敗的解決方法

    JavaScript使用focus()設置焦點失敗的解決方法

    這篇文章主要介紹了JavaScript使用focus()設置焦點失敗的一個解決方法 ,需要的朋友可以參考下
    2014-09-09
  • javascript分頁代碼(當前頁碼居中)

    javascript分頁代碼(當前頁碼居中)

    昨天看了妙味課堂的 分頁視頻教程,今天自己參照其思路,自己寫了下,并且自己新增了一個顯示頁碼個數(shù)的屬性 showPageNum
    2012-09-09
  • 我也種棵OO樹JXTree[js+css+xml]

    我也種棵OO樹JXTree[js+css+xml]

    我也種棵OO樹JXTree[js+css+xml]...
    2007-04-04
  • JavaScript錯誤處理避坑指南

    JavaScript錯誤處理避坑指南

    JavaScript錯誤處理是編程過程中不可避免的部分,它涉及到識別、捕獲和響應代碼運行時可能出現(xiàn)的問題,本文將詳細給大家介紹一下JavaScript錯誤處理的避坑指南,需要的朋友可以參考下
    2025-03-03

最新評論

习水县| 阿坝| 阿拉尔市| 祁连县| 孝昌县| 时尚| 娄底市| 开平市| 汉中市| 五原县| 博野县| 永寿县| 恩施市| 怀宁县| 大兴区| 望谟县| 光山县| 西丰县| 海淀区| 图木舒克市| 芦溪县| 阳高县| 望谟县| 新乡市| 桂东县| 莱芜市| 大悟县| 社会| 盐津县| 苏州市| 靖远县| 政和县| 集安市| 凭祥市| 密云县| 上栗县| 大关县| 林西县| 京山县| 息烽县| 芷江|