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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章