关于严格模式
'use strict'
console.log(document)//此处说明开启了严格模式,也能通过window点出其属性
// 只是window被隐藏了,但凡要打印window的地方,都会打印undefined
function hj() {
console.log(this)//严格模式下,打印undefined,非严格模式,打印window
}
hj()
console.log(window)//严格模式下,打印不出来window
一.this规则
首先是关于this指向的,我这里就不再赘述规则了
规则就两点,基本一切都是基于这个
1.this在函数中的指向永远由最后调用这个函数的东西决定,谁调用就指向谁
2.如果出现这一条,则第一条无效,即函数后出现.bind(A),那么无论谁最后调用这个函数,这个函数中的this都将指向A,因为这个函数在声明的时候,this就已经注定绑定成指向A了,不会再改了
众所周知,有call,apply,bind三种方法可以改变函数的this指向,但是call与apply是改变和执行同时,而bind是改变之后返回一个函数,再调用才会执行,其实内部实现想想也不难
顶多是let that = this,然后把所有内部的this换成传进来的那个,只是call,apply改完之后立马执行,bind改完之后,把改了的函数返回给你执行
还有一个点需要明白,箭头函数也类似于他们,能够在定义时把内部this指向外部this,内部this绑定死成外部this
调用的时候不会被调用的this影响了,内部的this已经固定死了
二.关于实例方法与属性和原型方法与属性,和类静态方法与属性的区别和作用范围,以及如何定义,以及是如何通过原型链找的
接下往他们身上加类和方法,实例,原型,静态,以及私有变量#的定义
类版 类中默认开启了局部严格模式,所以所有的window打印都会变成undefined
代码
class Person {
#id//实例私有变量,无法通过实例点出,而只能通过实例方法返回,比如此处的getId,这种写法非常相似于
// java类里的写法
// 有一点是,当我把#id都改为id,下面打印p.id之处的打印打印了100,说明#必须要有
constructor(id) {
this.cons = 'cons'//在实例身上 实例属性
this.consF = function () {
}//在实例身上 实例方法
this.#id = id
}
state = {}// 在实例身上----实例属性
sf() {
console.log(this)
}//在原型身上,原型方法
sf1 = function () {
console.log(this)
}//在实例身上 实例方法
sf2 = () => {
console.log(this)
}//在实例身上 实例方法
static state1 = {}//在构造器上--静态属性(只能类名取到 Person.state1)
static sf3 = function () {
console.log(1515)
}//在构造器上--静态方法(只能类名调用 Person.sf3())
getId() {
return this.#id
}//返回#id,这是返回id的唯一出口
}
let p = new Person(100)
console.log(p)//观察这些方法和属性的所在之处
// 此处验证sf1与sf2两种写法中的this的区别,此处比较的是实例身上两个方法
// 一个是function一个是箭头函数定义的, 看看this区别
let a = p.sf1
let b = p.sf2
p.sf1()//打印实例
p.sf2()//打印实例
a()//打印undefined
b()//打印实例对象,为何window调用内部this却指向实例,因为定义时为箭头函数方式,内部this已经
固定死了,固定死为当时定义函数时的外部this,sf2当时的外部this指向实例
此处和用bind有异曲同工之妙,箭头函数内外部相通,把函数中的this定死为实例了
// 此处验证sf中的this,此处看的是原型身上的方法sf
let c = p.sf
p.sf()//打印实例
c()//打印undefined
// 看看能否打印staic属性和调用static方法
console.log(a.state1, Person.state1)//undefined , {}
// a.sf3()//a.sf3 is not a function
Person.sf3()//1515
// 此处看看#定义的变量如何取到
// console.log(p.id)//undefined
// console.log(p.#id)//Uncaught SyntaxError: Private field '#id' must be declared in an enclosing class
console.log(p.getId())//100
图片
构造函数版 由于全局并没有开启严格模式,所以这里该打印window就照常打印的会是window
代码
function Human(id) {
let _id = 10
this._id = id
this.hh = 123//在实例身上 实例属性
this.jj1 = function () {
console.log(this)
}//在实例身上 实例方法
this.jj2 = () => {
console.log(this)
}//在实例身上 实例方法
}
Human.prototype.ll1 = function () {
console.log(this)
}//在原型身上,原型方法
Human.prototype.ll2 = () => {
console.log(this)
}//在原型身上,原型方法
Human.prototype.state = {} //在原型身上 原型属性
Human.hass = 150//在构造器上--静态属性(只能类名取到 Human.hass)
Human.hasu = function () {
console.log(1515)
}//在构造器上--静态方法(只能类名调用 Human.hasu())
Human.prototype.getId = function () {
return this._id
}
let h = new Human(100)
console.log(h)//观察这些方法和属性的所在之处
// 此处验证jj1与jj2两种写法中的this的区别, 此处比较的是实例身上两个方法
// 一个是function一个是箭头函数定义的, 看看this区别
let c = h.jj1
let d = h.jj2
// h.jj1()//打印实例
// h.jj2()//打印实例
// c()//打印window
// d()//打印实例,为何window调用内部this却指向实例,因为定义时为箭头函数方式,内部this已经
// 固定死了,固定死为当时定义函数时的外部this,jj2当时的外部this指向实例
// 此处验证ll1与ll2两种写法中的this的区别, 此处比较的是原型身上两个方法
// 一个是function一个是箭头函数定义的, 看看this区别
let a = h.ll1
let b = h.ll2
h.ll1()//打印实例
h.ll2()//打印window,为何实例调用内部this却指向window,因为定义时为箭头函数方式,内部this已经
// 固定死了,固定死为当时定义函数时的外部this,lll2当时的外部this指向window
a()//打印window
b()//打印window
// 看看能否打印staic属性和调用static方法
console.log(h.hass, Human.hass)//undefined , 150
// h.hasu()//h.hasu is not a function
// Human.hasu()//1515
// 此处看看#定义的变量如何取到
console.log(h.id)//undefined
console.log(h._id)//100 说明还是可以点出来....不太算私有变量
console.log(h.getId())//100
图片
类版和构造函数版区别总结
1.似乎class没地方直接在原型上放属性, 构造函数却可以直接在原型上放属性
2.在原型上放方法的方式class的话似乎只有一种方式,见类版中函数sf()
但是构造函数里,可以看到也只有一种方式,但是它可以改成箭头函数写法
见构造函数中函数,jj1 jj2
3.承接第3点可以看到的时候,我做了一个比较
那就是比较两个点
1.原型上的方法,用箭头函数和function定义的话,this有何同
2.实例上的方法,用箭头函数和function定义的话,this有何同
这里我也不再赘述和解释,依然是看第一点,this规则,就能明白为什么是这么打印了
三.关于react中this指向的问题,以及如何解决
问题
因为this是作为回调,没有被实例调用,而是作为回调调用,可以理解为window调了.....
也就是类似于下面这种情况,见函数speak
解决
而解决方法也很简单, 见stop
而react中的解决方法与此处一样
class Student {
constructor() {
}
speak() {
console.log(this)
}
stop = () =>
console.log(this)
}
let s = new Student()
let ns1 = s.speak
let ns2 = s.stop
ns1()//打印undefined
ns2()//打印实例
详细看看的话,可以看看我的这篇博客, 彻底弄懂js中的this指向 https://blog.csdn.net/qq_41430522/article/details/114608440
四,关于react中传参的问题,以及如何解决
可以看我这篇文章
react学习--持续更新 https://blog.csdn.net/qq_41430522/article/details/114521843里面的第6点
五,关于vue与react中传参的一个小知识点(不传参时的默认值),以及不同之处
可以看我这篇文章
关于vue与react中点击事件绑定的小知识与区别 https://blog.csdn.net/qq_41430522/article/details/114950610
六.关于dom的一些东西
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id='hh'>
<div class="kj"></div>
</div>
<p class="jj"></p>
<span class="ll"></span>
</body>
</html>
<script>
let hh = document.querySelector('#hh')
let jj = document.querySelector('.jj')
let ll = document.querySelector('.ll')
let kj1 = hh.querySelector('.jj')
let kj2 = hh.querySelector('.kj')
console.log(kj1, kj2)//可以卡到kj1拿不到,kj2拿到了,显然只能拿范围内的
console.log(document)
// 一个类有多个子类继承它,这些子类可以分化出不同的原型链
// 但顶端都是继承自一个类
// 同样这些子类的子类也可以继承同一个类
// 所以说起来,类之间继承等的关系确实是可以混杂
// 所以看到错综复杂的原型关系也就不用奇怪了
// debugger
console.dir(hh) //----_proto_ =>
// HTMLDivElement-----_proto_ =>
// HTMLElement-----_proto_=>
// Element-----_proto_=>
// Node----_proto_=>
// EventTaeget-----_proto_=>
// Object 到此就到达顶部Object构造函数了
console.dir(jj)//----_proto_ =>
// HTMLParagraphElement-----_proto_ =>
// HTMLElement-----_proto_=>
// Element-----_proto_=>
// Node----_proto_=>
// EventTaeget-----_proto_=>
// Object 到此就到达顶部Object构造函数了
console.dir(ll)
//----_proto_ =>
// HTMLSpanElement-----_proto_ =>
// HTMLElement-----_proto_=>
// Element-----_proto_=>
// Node----_proto_=>
// EventTaeget-----_proto_=>
// Object 到此就到达顶部Object构造函数了
console.log(window)
console.dir(document)//----_proto_=>
// HTMLDocument----_proto_=>
// Document------_proto_=>
// Node----_proto_=>
// EventTaeget-----_proto_=>
// Object 到此就到达顶部Object构造函数了
// querySelector等方法就在构造函数Document身上,Elment构造函数身上也有
// 再写window.document
// 每个元素都能queryselect,因为这是原型链上的 let hh = document.querySelector('#hh') hh.querysect可以.....
// 那么也可以直接 div.queryselct吗,div在window上吗
// 还是说叫别的名字,HTMLDIVElment.queryselct ?
// 毕竟canvas的原型就是HTMLCANVASElment
// 他们的共同原型是Document?
// 打印看看就知道了
// 遗留问题,浏览器是怎么拿到编辑器里的html的,正则遍历吗
// 拿到之后,浏览器又是怎么解析渲染的,之后展示成页面
</script>