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/

相关推荐
疯狂成瘾者1 分钟前
Chroma向量数据库
开发语言·数据库·c#
我是唐青枫4 分钟前
C#.NET Monitor 与 Mutex 深入解析:进程内同步、跨进程互斥与使用边界
开发语言·c#·.net
bbq粉刷匠4 分钟前
Java--剖析synchronized
java·开发语言
ou.cs7 分钟前
c# 信号量和锁的区别
开发语言·c#
Gofarlic_OMS8 分钟前
装备制造企业Fluent许可证成本分点典型案例
java·大数据·开发语言·人工智能·自动化·制造
阿赛工作室17 分钟前
Vue中onBeforeUnmount不触发的解决方案
前端·javascript·vue.js
码王吴彦祖18 分钟前
顶象 AC 纯算法迁移实战:从补环境到纯算的完整拆解
java·前端·算法
Freak嵌入式18 分钟前
MicroPython LVGL基础知识和概念:显示与多屏管理
开发语言·python·github·php·gui·lvgl·micropython
yu859395823 分钟前
matlab雷达信号与干扰的仿真
开发语言·matlab
前进的李工23 分钟前
LangChain使用AI工具赋能:解锁大语言模型无限潜力
开发语言·人工智能·语言模型·langchain·大模型