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/

相关推荐
Tracy-2221 小时前
广东专升本计算机C语言
c语言·开发语言
多多*21 小时前
牛客周赛 Round 117 ABCDE 题解
java·开发语言·数据结构·算法·log4j·maven
liu****21 小时前
13.POSIX信号量
linux·开发语言·c++·算法·1024程序员节
Macbethad21 小时前
Typora 精通指南:掌握高效 Markdown 写作的艺术
前端·macos·前端框架
F_Director21 小时前
Webpack DLL动态链接库的应用和思考
前端·webpack·性能优化
唆了蜜.21 小时前
ESLint: Expected indentation of * spaces but found *. (style/indent)
开发语言·javascript·vue·webstorm
生信小窝21 小时前
基于R获取全球海岸线数据获取与导出
开发语言·r语言
益达是我1 天前
【element-plus】element-plus升级到v2.11.7,el-tree文字不显示问题
前端·javascript·vue.js·element-plus
程序员卷卷狗1 天前
联合索引的最左前缀原则与失效场景
java·开发语言·数据库·mysql
2739920291 天前
qInstallMessageHandler(重定向至log文件)
开发语言·qt