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/

相关推荐
Zha0Zhun5 分钟前
一个使用ViewBinding封装的Dialog
前端
兆子龙6 分钟前
从微信小程序 data-id 到 React 列表性能优化:少用闭包,多用 data-*
前端
滕青山6 分钟前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js
时光不负努力8 分钟前
编程常用模式集合
前端·javascript·typescript
大雨还洅下13 分钟前
前端JS: 跨域解决
javascript
恋猫de小郭15 分钟前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios
小岛前端19 分钟前
Node.js 宣布重大调整,运行十年的规则要改了!
前端·node.js
OpenTiny社区20 分钟前
OpenTiny NEXT-SDK 重磅发布:四步把你的前端应用变成智能应用
前端·javascript·ai编程
梦想CAD控件36 分钟前
在线CAD开发包结构与功能说明
前端·javascript·vue.js
张拭心41 分钟前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能