我們先說一個最簡單的this在全域指向的是什么呢?
這個問題很簡單在瀏覽器中測驗this,全域指向的是window,不過在開發程序中this很少在全域使用,一般都是在函式內的
this有幾種系結規則?
系結一:默認系結
// 1.案例一:
function foo() {
console.log(this)
}
foo()//window
// 2.案例二:
function foo1() {
console.log(this)
}
function foo2() {
console.log(this)
foo1()
}
function foo3() {
console.log(this)
foo2()
}
foo3()//window
// 3.案例三:
var obj = {
name: "why",
foo: function() {
console.log(this)
}
}
var bar = obj.foo
bar() // window
系結二:隱式系結
// 1.案例一:
var obj = {
name: "why",
foo: foo
}
obj.foo() // obj物件
// 2.案例二:
var obj = {
age: "哈哈哈",
eating: function () {
console.log(this + "在吃東西")
},
running: function () {
console.log(this + "在跑步")
}
}
obj.eating()//obj物件
obj.running()//obj物件
var fn = obj.eating
fn()
//window,為什么是window呢因為把obj.eating這個函式賦值給了fn,fn在全域呼叫的所以指向的是window
// 3.案例三:
var obj1 = {
name: "obj1",
foo: function () {
console.log(this)
}
}
var obj2 = {
name: "obj2",
bar: obj1.foo
}
obj2.bar()//obj2物件
系結三:顯示系結
function foo() {
console.log("函式被呼叫了", this)
}
//1.foo直接呼叫和call/apply呼叫的不同在于this系結的不同
//foo直接呼叫指向的是全域物件(window)
foo()
var obj = {
name: "obj",
// age:foo//可以簡寫這一步
}
//call/apply是可以指定this的系結物件
foo.call(obj)//obj物件
foo.apply(obj)//obj物件
foo.apply("aaaa")//aaaa
// 2.call和apply有什么區別?
function sum(num1, num2, num3) {
console.log(num1 + num2 + num3, this)
}
sum.call("call", 20, 30, 40)//傳遞引數后面可以傳無限個數值,都是用逗號分割
sum.apply("apply", [20, 30, 40])//傳遞引數用陣列接收,一樣可以傳無限個數值,用逗號分割
// 3.call和apply在執行函式時,是可以明確的系結this, 這個系結規則稱之為顯示系結
系結四:new系結
// 我們通過一個new關鍵字呼叫一個函式時(構造器), 這個時候this是在呼叫這個構造器時創建出來的物件
// this = 創建出來的物件
// 這個系結程序就是new 系結
function Person(name, age) {
this.name = name
this.age = age
}
var p1 = new Person("哈哈哈", 18)
console.log(p1.name, p1.age)//哈哈哈,18
var p2 = new Person("呵呵呵", 30)
console.log(p2.name, p2.age)//呵呵呵,30
這些的案例可以給我們什么樣的啟示呢?
1.函式在呼叫時,JavaScript會默認給this系結一個值;
2.this的系結和定義的位置(撰寫的位置)沒有關系;
3.this的系結和呼叫方式以及呼叫的位置有關系;
4.this是在運行時被系結的;
最后說一下默認系結和顯示系結bind沖突: 優先級(顯示系結)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/386605.html
標籤:其他
