通过以下例子来观察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);
}
}