js中關於this的指向和js原型的一些經驗

通過以下例子來觀察this的指向,以及得出的結論

console.log(this)
function test(){
	this.name={
		opactiy:12
	}
	this.f2=function(){
		console.log(this)
		function fun(){
			console.log(this)
		}
		fun()
	}
	this.f3=()=>{
		console.log(this)
		fun=()=>{
			console.log(this)
		}
		fun()
	}
	this.f4=()=>{
		console.log(this)
		function fun(){
			test=()=>{
				console.log(this)
			}
			test()
		}
		fun()
	}
}

//通過new test函數 實例一個test對象 js對象都是由函數構建的 此例的當前對象是v1
let v1=new test()//加不加括號都行

/*	
	1.this不能賦值
	2.this默認指向window對象
	3.函數屬性如果是使用function聲明的函數,那麼this指向的就是指定函數構造的當前對象
	4.使用function聲明的函數中this指向window對象,除了函數屬性 由f2()的this輸出可得知(test,window)
	5.簡頭函數中的this指向最近的上下文中的this 由f4()的this輸出可得知(test,window),第一個this最近的上下文是test函數,test函數中this指向的是當前對象,第二個this的上下文是fun函數,由結論4可得this指向的是window對象
*/
v1.f2()
v1.f3()
v1.f4()

/*	
	3.函數屬性如果是使用function聲明的函數,那麼this指向的就是指定函數構造的當前對象 此例對象是v1
	5.簡頭函數中的this指向最近的上下文中的this,v1是test對象,所以,tset簡頭函數最近的上下文是test函數,test函數指向當前對象也就是v1
	以下f2賦值等同於在test函數中
	this.f2=function(){
		tset=()=>{
			console.log(this)
		}
		tset()
	}
*/
v1.f2=function(){
	tset=()=>{
		console.log(this)
	}
	tset()
}

v1.f2()

/*	
	5.簡頭函數中的this指向最近的上下文中的this 這裏是window
*/
v1.f2=()=>{
	console.log(this)
}
v1.f2()

輸出結果如下:
在這裏插入圖片描述
總結如下
1.this不能賦值
2.this默認指向window對象
3.函數屬性如果是使用function聲明的函數,那麼this指向的就是當前對象
4.使用function聲明的函數中this指向window對象,除了函數屬性
5.簡頭函數中的this指向最近的上下文中的this
再看一個例子,加深印象
在這裏插入圖片描述

再看看原型的規則
1.對象默認存在的__proto__對象屬性這個對象的原型
2.對象的__proto__對象屬性默認是構建當前對象函數的prototype對象屬性
3.對象屬性也是Ojbect類型對象(那麼也就是由Object函數構造的對象)由結論2可得普通對象(new Object/ { })的原型是Object.prototype
4.對象找不到的屬性就會去自身的__proto__(原型)對象屬性尋找,原型對象屬性本身也是對象它會找自身的__proto__對象屬性,直到一個__proto__對象是Object對象,這個對象的__proto__(原型)也就是Object.prototype,對象的這個查找過程就是原型鏈。
5.Object.prototype對象屬性是原型鏈的終點,因爲Object.prototype對象的__proto__屬性是null
6.對象的__proto__對象屬性不是Object類型的對象,是指定函數類型的對象,這個對象的原型就是一個Object對象。
原型其實很簡單,原型鏈就是js對象的__proto__屬性一種查找關係,看兩個例子吧8
如上個例子的v1對象打印結果如下所示
在這裏插入圖片描述

v1的原型鏈如下所示
首先,v1是個test對象,然後test對象的構造函數是test函數,所以v1的原型是test.prototype。
其次,test.prototype自身也是個Object,那麼Object對象的構造函數是Object函數,所以test.prototype的原型是Object.prototype

test=>test.__proto__(test.prototype)
=>test.prototype.__proto__(Object.protoytp)
=>Object.prototype.__proto__(null)

再看一個例子
在這裏插入圖片描述
首先,[](new Array)是個Array對象,然後Array對象的構造函數是Array函數,所以Array對象的原型(proto)是Array.prototype,Array.prototype本身也是個Arrray對象(帶字符串下標的數組對象無論多長都是0),但它也是__proto__對象屬性,按照理論6,Array.prototype是一個不是Object類型的對象,它的原型就是一個Object對象。

Array=>Array.__proto__(Array.prototype(new Array(Array方法都在這裏瞭如splice..)))
=>Array.prototype.__proto__(Object.prototype)=>Object.prototype.__proto__=>null

數組也是Object對象是對象就可以隨便生成新屬性,Array函數就提供了一個length屬性,其它啥也沒有。數組也是Object對象,但是在語法概念上還是不一樣的。必竟一個是[]一個是{}。
在這裏插入圖片描述
這是我的一個總結,可能不完全對,js的原型太繞了
真要用Js原型的話就用class算了,不管了直接上普通語言的oop

class Student {
    constructor(name) {
        this.name = name;
    }

    hello() {
        alert('Hello, ' + this.name + '!');
    }
}
class PrimaryStudent extends Student {
    constructor(name, grade) {
        super(name); // 記得用super調用父類的構造方法!
        this.grade = grade;
    }

    myGrade() {
        alert('I am at grade ' + this.grade);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章