动态

详情 返回 返回

JavaScript中的this綁定 - springboot實戰電商項目mall4j - 动态 详情

springboot實戰電商項目mall4j (https://gitee.com/gz-yami/mall4j)

java商城系統源碼

JavaScript中的this綁定

在日常的開發中,我們會經常使用JavaScript中的一個關鍵字:this,在常見的編程語言中,幾乎都有this這個關鍵字,但是JavaScript中的this和常見的變成語言中的this不太一樣,
在常見的變成語言(java,c++等)中,this通常只會出現在類的方法中,而this指向它當前調用的對象,但是在JavaScript中,this是更加靈活的,無論是它出現的位置還是它代表的含義。

this全局作用下的指向

這個問題非常容易回答,在瀏覽器中,this的指向為全局對象window

console.log(this) // window 對象

var name = "hhf"

console.log(this.name) // hhf
console.log(window.name) // hhf

但是,開發中很少直接在全局作用於下去使用this,通常都是在函數中使用的

this到底指向什麼呢?

下面我們通過一段代碼,代碼中,我們定義一個函數,對他進行三種不同的方式進行調用,它產生了不同的結果

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

foo() // window對象

const obj = {
  name: "hhf",
  foo: foo
}

obj.foo() // obj1

const obj2 = {}

foo.call(obj2) // obj2

從上面代碼運行的結果我們得出:

1.函數在調用時,JavaScript會默認給this綁定一個值;
2.this的綁定和定義的位置(編寫的位置)沒有關係;
3.this的綁定和調用方式以及調用的位置有關係;
4.this是在運行時被綁定的

在JavaScript中,this有四種綁定規則,分別是:
1.默認綁定
2.隱式綁定
3.顯式綁定
4.new綁定

下面我們分別對這四種綁定規則進行學習

默認綁定

默認綁定通常是在獨立函數進行調用時進行綁定,獨立函數調用我們可以理解成沒有被綁定到某個對象進行調用,默認綁定在瀏覽器中指向的是window,當為嚴格模式(use strict)的時候指向的是undefined

// 案例一
function foo() {
  console.log(this)
}

foo() // window對象

// 案例二
function foo(fn) {
  fn()
}

const obj = {
  name: "hhf",
  bar: function() {
    console.log(this)
  }
}


foo(obj.bar) // window

顯示綁定

顯示綁定通常是某個對象對它進行調用,通俗來講:誰調用就指向誰

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

const obj = {
  name: "hhf",
  bar: foo
}


obj.bar() // hhf

隱示綁定的另一種情況:

當有多層對象嵌套調用某個函數的時候,如 對象.對象.函數 ,this 指向的是最後一層對象。

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

const person = {
  name: "person"
}

person.foo = foo

const obj = {
  name: "hhf",
  bar: foo,
  person: person
}

obj.person.foo() // person

顯式綁定

在JavaScript中,所有的函數都可以使用call、apply、bind三個方法對函數的this進行綁定
使用方式的不同:call、apply在函數調用時對它進行調用,bind會返回一個新的函數

顯示綁定的用途: 防抖、節流等

call函數的使用

call() 方法使用一個指定的 this 值和單獨給出的一個或多個參數來調用一個函數。
它接收的參數為:第一個為綁定的this,後面接上的為所調用的函數的參數
具體使用方法如下

// 基本使用
function foo() {
  console.log(this.name);
}

const obj = {
  name: "hhf"
}


foo.call(obj) // hhf

// 傳入參數
function foo(n, m) {
  console.log(this.name);
  console.log(n, m)
}

const obj = {
  name: "hhf"
}


foo.call(obj, "n", "m") // hhf n m

apply函數的使用

apply方法的語法和作用與 call() 方法類似,只有一個區別,就是 call() 方法接受的是一個參數列表,而 apply() 方法接受的是一個包含多個參數的數組。
具體使用方法如下

function foo(n, m) {
  console.log(this.name);
  console.log(n, m)
}

const obj = {
  name: "hhf"
}


foo.call(obj, ["n", "m"]) // hhf, n m

bind函數的使用

bind函數它所接收的參數和call函數一樣,但是它會返回一個新的函數,新的函數的this會指向傳入的對象

function foo(n, m) {
  console.log(this.name);
  console.log(n, m)
}

const obj = {
  name: "hhf"
}


const newFoo = foo.bind(obj, "n", "m")

newFoo() // hhf n m

new 綁定

new是JavaScript中的一個關鍵字,當進行new操作調用函數時,會執行如下的操作
1.函數內部會創建一個新的對象
2.創建的對象的原型(__proto__)會指向函數的prototype
3.所創建的對象會綁定到該函數的this上
4.如果函數沒有其他返回值,會默認返回該對象

function Persion() {
  console.log(this)
}

new Persion(); // Persion {}

規則優先級

上面我們學習了四種綁定規則,那麼我們可能會思考,如果一個函數在調用的時候使用了多種綁定規則,誰的優先級最高呢?
結果如下
1.默認規則的優先級最低p毫無疑問,默認規則的優先級是最低的,因為存在其他規則時,就會通過其他規則的方式來綁定this
2.顯示綁定優先級高於隱式綁定

function foo() {
  console.log(this.name)
}

const obj1 = {
  name: 'obj1',
  foo: foo
}

const obj2 = {
  name: 'obj2',
}

obj1.foo.call(obj2) // obj2

3.new綁定優先級高於隱式綁定

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

const obj1 = {
  name: 'obj1',
  foo: foo
}

const obj2 = {
  name: 'obj2',
}

new obj1.foo() // foo {}

4.new綁定優先級高於bind
new綁定和call、apply是不允許同時使用的,所以不存在誰的優先級更高
new綁定可以和bind一起使用,new綁定優先級更高p代碼測試

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

const obj1 = {
  name: 'obj1',
  foo: foo
}

const newFoo = foo.bind(obj1)
new newFoo() // foo {}

箭頭函數的this

箭頭函數是ES6中新增的一種函數的寫法,但是箭頭函數是不綁定this的,當在箭頭函數中使用this時,它會隨着它的作用域網上找,使用最近的作用域的this來使用

// 使用普通函數

const obj1 = {
  name: 'obj1',
  foo: function() {
    console.log(this)
  }
}

obj1.foo() // obj1

// 使用箭頭函數
const obj1 = {
  name: 'obj1',
  foo: ()=> {
    console.log(this)
  }
}

obj1.foo() // window foo的上層作用域為window

// setTimeout所傳入的函數如果是普通函數,那麼它綁定的是全局對象window,如果傳入的是一個箭頭函數,那麼它的this執行是它的上層作用域的this指向
const obj1 = {
  name: 'obj1',
  bar: function() {
    setTimeout(()=> {
      console.log(this)
    })
  }
}

obj1.bar() // obj1

下面我們通過一道題,對剛剛所學的進行一個小練習

var name = "window"

function Person(name) {
  this.name = name
  this.obj = {
    name: "obj",
    foo1: function() { 
      return function() {
        console.log(this.name)
      }
    },
    foo2: function() {
      return ()=>{
        console.log(this.name)
      }
    }
  }
}

var person1 = new Person("person1")
var person2 = new Person("person2")

person1.obj.foo1()()
person1.obj.foo1.call(person2)()
person1.obj.foo1().call(person2)

person1.obj.foo2()()
person1.obj.foo2.call(person2)()
person1.obj.foo2().call(person2)

輸出結果為

/*
window
window
person2
obj
person2
obj
*/

springboot實戰電商項目mall4j (https://gitee.com/gz-yami/mall4j)

java商城系統源碼

Add a new 评论

Some HTML is okay.