let声明的全局变量不是window对象属性
今天在控制台写删除数组第一个元素的代码时,发现了一个问题,以下是书中源码,
- let arr = [1,2,3,4,5]
- Array.prototype.reIndex = function (myArray) {
- const newArray = [];
- for (let i=0; i<myArray.length; i++) {
- if (myArray[i] !== undefined) {
- newArray.push(myArray[i]);
- }
- }
- return newArray;
- }
- Array.prototype.removeFirPos = function () {
- for (let i=0;i<this.length;i++){
- this[i] = this[i+1]
- }
- return this.reIndex(this)
- }
- arr = arr.removeFirPos()
- console.log(arr)//控制台输出
按这个源码,我进行了更改,使用了箭头函数,如下
- let arr = [1,2,3,4,5]
- Array.prototype.reIndex = (myArray) => {
- const newArray = [];
- for (let i=0; i<myArray.length; i++) {
- if (myArray[i] !== undefined) {
- newArray.push(myArray[i]);
- }
- }
- return newArray;
- }
- Array.prototype.removeFirPos = () => {
- for (let i=0;i<this.length;i++){
- this[i] = this[i+1]
- }
- return this.reIndex(this)
- }
- arr = arr.removeFirPos()
- console.log(arr)//控制台输出
然后发现报错,typeerror:this.reIndex is not a function。查找下发现箭头函数没有自己的this。
我又想了一下,变量arr调用方法removeFirPos(),那么这个this不就是指向了arr吗,后来一想。。。这不是非箭头函数时候的指向嘛
然后继续网络查找找到了一句话:由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值
所有this的指向在非严格模式下是window。为了更好的理解我编写以下代码
- function Test1() {
- console.log(this);
- setTimeout(() => {
- console.log('这是箭头函数',this)
- })
- }
- function Test2() {
- console.log(this);
- setTimeout(function () {
- console.log('这是普通函数',this)
- })
- }
- let t1 = new Test1()
- let t2 = new Test2()
输出结果如下
VM90:2 Test1 {}
VM90:9 Test2 {}
VM90:4 这是箭头函数 Test1 {}
VM90:11 这是普通函数 Window {window: Window, self: Window, document: document, name: "", location: Location, …}
原因是箭头函数捕获的是其所在上下文中的this值,而由于setTimeout()调用的代码运行在所在函数完全分离的执行环境上,this指向的是window(其实我也没咋明)
到这基本原因就明确了。
后面在我查找知识的时候,发现了let和var声明的不同,贴下人家的代码,这是在知乎找的(https://zhuanlan.zhihu.com/p/149239478)
- var bar = {
- myName:"bar",
- printName: function () {
- console.log(myName)
- }
- }
- let myName = "global"
- let _printName = bar.printName
- _printName() // global
- bar.printName() // global
对于这个代码都比较好理解,前面全局变量bar,myName,_printName的声明,然后_printName声明这行,bar.printName是一函数,让变量_printName执行了这一函数
然后在全局作用域下直接调用了函数,则输出的myName将在全局域中查找为global;最后一行相同原理
然后对代码稍加更改
- var bar = {
- myName:"bar",
- printName: function () {
- console.log(this.myName)
- }
- }
- let myName = "global"
- let _printName = bar.printName
- _printName() // undefined
- bar.printName() // bar
仍然是_printName变量执行函数bar.printName,这次执行时因为是全局作用域下,输出的应该是window.myName。这下问题出来了,全局作用域下不是有myName吗
非也,起初我也迷惑,但后来代码放在控制台跑一下,发现其实let声明变量的作用域并非全域,而是在script域中,也就是说全域并没有myName这一变量,故输出undefined
bar调用函数printName执行,则执行环境在bar块作用域中,故输出bar
萌新小白,请教
let声明的全局变量不是window对象属性的更多相关文章
- 全局变量都是window对象的属性
var x = "haha"; var test = function(){ alert(this.x); } 上述,则会弹出 haha的值. 因为在JavaScript的变量作 ...
- javascript window对象属性和方法
window对象 window对象表示一个浏览器窗口或一个框架.在客户端JavaScript中,window对象是全局对象,所有的表达式 都在当前的环境中计算.也就是说,要引用当前窗口根本不需要特殊的 ...
- window对象属性alert、confirm、prompt怎么使用?
window对象属性alert.confirm.prompt怎么使用? 一.总结 1.参数依次复杂,返回值依次复杂,但是感觉都是一一继承的,所以很好想也很好写. 二.window对象alert.con ...
- JavaScript Window对象属性
window 代表浏览器中一个打开的窗口. Window的属性 属性 描述 closed 获取引用窗口是否已关闭. defaultStatus 设置或获取要在窗口底部的状态栏上显示的缺省信息. dia ...
- 【repost】js window对象属性和方法相关资料整理
window对象有以下方法: open close alert confirm prompt setTimeout clearTimeout setInterval clearInterval mov ...
- 使用BOM 的window对象属性打开新窗口
★ 示例1 要求:弹出新窗口,并向新窗口写入动态HTML代码 代码 <buttononclick="btnOpen()">打开新窗口</button> & ...
- Window对象属性
2018-11-28 12:21:20
- Window对象
Window对象: Window 对象表示浏览器中打开的窗口,如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框 ...
- 第十二章:window对象
第十一章介绍了window对象及其客户端javascript所扮演的核心角色:它是客户端javascript程序的全局对象.本章介绍window对象的属性和方法,这些属性定义了不同的API,但是只有一 ...
随机推荐
- Top Coder 某场Div 2的C题 题解
前天,我们了解了一下一种叫做树状数组的神奇玩意儿,今天就放一道真题来检验一下自己的学习成果吧! 嗯,题目就是这样的啦. 分析: 这题的暴力大家应该都会打吧. 注意到m小的压批,所以对于每一个m值,我们 ...
- php-fpm 的各种启动方式
启动 php-fpm 最简单的操作: /usr/local/php/sbin/php-fpm php 5.3.3 以后的php-fpm 不再支持 php-fpm 以前具有的 /usr/local/ph ...
- JVM系列【5】JVM常用指令
JVM系列笔记目录 虚拟机的基础概念 class文件结构 class文件加载过程 jvm内存模型 JVM常用指令 GC与调优 指令集分类 基于寄存器的指令集 基于栈的指令集 Hotspot中的Loca ...
- mysql通配符_,%查询
模糊查询 在使用模糊查询的时候,mysql使用的是最左原则,所以模糊查询语句: select * from sys_user where user_name like '#{userName}%' 我 ...
- centos8平台使用strace跟踪系统调用
一,strace的用途 strace 是最常用的跟踪进程系统调用的工具. 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectfore ...
- ansible用authorized_key模块批量推送密钥到受控主机(免密登录)(ansible2.9.5)
一,ansible的authorized_key模块的用途 用来配置密钥实现免密登录: ansible所在的主控机生成密钥后,如何把公钥上传到受控端? 当然可以用ssh-copy-id命令逐台手动处理 ...
- 立即执行函数 - Js函数笔记
立即执行函数 定义:此类函数没有声明,在执行一次后即释放,适合做初始化. 针对初始化功能的函数,同时遵循一句话,只有表达式才能被执行符号执行 1.(function() {...}()); - W3C ...
- IDEA Cannot resolve plugin org.apache.maven.plugins:maven-site-plugin:3.8.2-plugin爆红错误
如果确认本地库存在,maven仓库配置正确,将其显式声明出来,问题解决 <!--报找不到该依赖的错误, 本地库又存在,将其显式声明在这里,问题解决--> <plugin> &l ...
- Vue(学习第三部 自动化工具 [vue-cli])
目录 Vue自动化工具(Vue-cli) 安装nide.js npm 安装Vue-sli 使用Vue-处理初始化创建起那段项目 vue项目执行流程图 单文件组件的使用 template 编写HTML代 ...
- Mac 搭建 Redis 集群
date: 2020-09-24 16:24:00 updated: 2020-09-24 17:30:00 Mac 搭建 Redis 集群 参考文档 摘要 安装docker brew cask in ...