通過以下例子來觀察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);
}
}