一篇总结型文章,this,react中的this,document等node节点原型,实例和原型上的方法属性区分等

关于严格模式

'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>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值