js前端this指向规则

一言以蔽之:

  • this只和调用方式(调用者)有关
  • this是在运行时被绑定的

直接调用

当函数直接调用时,this指向的是window

js 复制代码
      function foo() {
        console.log(this)
      }

      foo()

打印结果:

object Window

隐式绑定(对象)

当函数是以对象调用时,打印的是调用的对象

js 复制代码
      function foo() {
        console.log(this)
      }

      var obj1 = {
        name: "obj1",
        foo: foo
      }

      obj1.foo()

打印结果:

{

"name": "obj1"

}

显式绑定(call/apply/bind)

分为call/apply和bind

js 复制代码
      function foo(name,age) {
        console.log(this,name,age)
      }

      var obj1 = {
        name: "obj1",
        foo: foo
      }

      foo.call(obj1,'zhangsan',18)
      foo.apply(obj1,['zhangsan',18])

      var bar = foo.bind(obj1,'zhangsan',18)
      bar()

执行结果:

new关键字绑定this

首先要清楚,new调用流程:(通过new关键字创建一个新对象的步骤是什么/构造函数时如何创建新对象的)

  • 创建一个新的对象
  • 空的对象的__proto__属性指向构造函数的Prototype属性(原型链)
  • 执行构造函数,如果构造函数中有this,则将this指向这个对象
  • 返回创建的对象
js 复制代码
      function foo(name) {
        console.log(this) // foo{}
        this.name = name // foo{name:'obj1'}
      }
      var obj1 = new foo('obj1')

优先级

new>显式>隐式

经典面试题分析1

js 复制代码
		// 错误的题目
        function foo(){
            console.log(this)
        }
        var obj1 = {
            name:'obj1',
            foo: foo
        }
        var obj2={
            name:'obj2'
        }
		// 错误原因在这里没有分号
		// 由js的自动分号插入(ASI)导致
		// 参考:https://juejin.cn/post/7325243117861519370
        (obj2.foo = obj1.foo)()

报错:

index.html:21 Uncaught TypeError: Cannot set properties of undefined (setting 'foo')

at index.html:21:19

(anonymous) @ index.html:21

正确的题目

复制代码
        function foo(){
            console.log(this)
        }
        var obj1 = {
            name:'obj1',
            foo: foo
        }
        var obj2={
            name:'obj2'
        }; // 这里有分号

        (obj2.foo = obj1.foo)()

结果:

window

这里的(obj2.foo = obj1.foo)()等价于foo(),显然属于直接调用,打印window

参考:https://juejin.cn/post/7325243117861519370

经典面试题分析2

js 复制代码
        var name = '全局window'
        var person = {
            name: 'person',
            sayName: function(){
                console.log(this.name)
            }
        }
        function sayName(){
            var fun = person.sayName
            fun() // window
            person.sayName();
            (b = person.sayName)()
        }
        sayName()

结果:

这里还有个注意点,当我们不声明name这个变量,window.name这个也是存在的,默认是一个空字符串。

并且,如果你①先运行上面这段代码,②再把var name = '全局window'这句注释,③刷新页面,会发现还是显示全局window而不是空字符串!这里的原理是:

window.name是一个所有浏览器都有的属性,表示浏览器窗口的名称,默认是一个空字符串,所有浏览器都是个空字符串。

window.name有个很有意思的跨页面特性,具体描述为:页面如果设置了window.name,即使进行了页面跳转到了其他页面,这个window.name还是会保留,刷新也是。

可以参考:https://www.zhangxinxu.com/wordpress/2019/09/window-name/

相关推荐
云姜.4 分钟前
java多态
java·开发语言·c++
CoderCodingNo13 分钟前
【GESP】C++五级练习题 luogu-P1865 A % B Problem
开发语言·c++·算法
陳103019 分钟前
C++:红黑树
开发语言·c++
一切尽在,你来25 分钟前
C++ 零基础教程 - 第 6 讲 常用运算符教程
开发语言·c++
泉-java26 分钟前
第56条:为所有导出的API元素编写文档注释 《Effective Java》
java·开发语言
0思必得027 分钟前
[Web自动化] Selenium处理滚动条
前端·爬虫·python·selenium·自动化
Misnice29 分钟前
Webpack、Vite、Rsbuild区别
前端·webpack·node.js
青茶36030 分钟前
php怎么实现订单接口状态轮询(二)
前端·php·接口
weixin_499771551 小时前
C++中的组合模式
开发语言·c++·算法
初级代码游戏1 小时前
套路化编程 C# winform 自适应缩放布局
开发语言·c#·winform·自动布局·自动缩放