js 杂症,this with 变量提升
一、this.xx 和 xx 是两回事
受后端语言影响,总把this.xx 和xx 当中一回事,认为在function中,xx 就是this.xx,其实完全两回事;
this.xx 是沿着this 原型链找变量,xx是沿着作用域链找变量
var func = function(){
console.info(this);
} var func1 = function(){
function func11(){
console.info(this) // 应该是func1
this.func(); // this 是window
func(); // windows 输出
}
console.info(this)
func11(); // 全局调用,func11 里面的this是全局对象window, 见下面的2
//this.func11(); //失败,this是window,没有func11方法
} func1()
元原型链:this.xxx 的时候会沿着原型链查找,继承可以通过原型链实现
作用域链:xxx 的时候会沿着作用域链查找,with 会设置作用域链最底层
二、this代表啥
this对象根据不同的调用方式,所绑定的对象也是不同的。
函数调用有四种:
1. 方法模式的调用:当一个函数被保存为一个对象的属性时,我们称这个函数为一个方法。当一个方法被调用时,this绑定到该对象。
var p = {func: func1}
p.func()// func1中的this就p
2. 函数模式的调用:当一个函数并非一个对象的属性时,那么它就被当作一个函数来调用,this被绑定到全局对象。
3. 构造器模式的调用:如果一个函数前面带上new来调用,那么将创建一个隐藏连接到该函数的prototype成员的新对象,同时this被绑定到这个新对象上。
function person(){
console.info(this);
this.age = 10;
}
var a = new person()
4. apply模式的调用:apply方法接收两个参数,第一个被绑定到this,第二个是参数数组。什么也不传时,默认this绑定到全局对象。
var person = function(){
this.age = 10;
this.say = function(){console.info(this.age)}
} var zl = function(){
person.call(this)
console.info(this)
} var a = new zl()
// 下面这个其实是错误的继承,涉及到变量提升,
var person;
var zl;
person = function(){
this.age = 10;
this.say = function(){ console.info(this.age) }
}
zl = function(){
console.info(zl);//其实是给zl 加了属性、方法
person.call(zl);
}
// 执行
var a = new zl() // 执行时候,zl, person 都已经定义出来了,在执行zl() 的时候,会沿着作用域链找到zl
三、变量提升
-----------------
say()
console.info(a); function say(){
console.info(111)
} var a = 100; -----------js解析后为,然后其实是执行下面的代码---------
function say(){
console.info(111)
}
var a; say()
console.info(a)
a = 100;
四、一个奇怪的事情,with,变量提升,this
({
x: 10,
foo: function () {
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
var x = 20;
var y = 30;
bar.call(this);
}
}
}).foo();
----js引擎解析翻译后----
({
x: 10,
foo: function () {
var x;
var y;
function bar() {
console.log(x); // 沿着作用域找到了foo 下面的x=undefined
console.log(y); // 沿着作用域链找到 foo 下面的 y=30
console.log(this.x);// this 是最外面的对象,x 已经改为20
}
with (this) {
x = 20; //this是最外面的对象,有x,其实是赋值给了this.x, 10变成20
y = 30; // this 没有y,沿着作用域链找到 foo 下面的y, undefine 变成30 bar.call(this);
}
}
}).foo();
题目来自 http://luopq.com/2016/02/14/js-with-keyword/
输出:
undefine
30
20
js 杂症,this with 变量提升的更多相关文章
- JS 函数作用域及变量提升那些事!
虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...
- js笔记——js里var与变量提升
var是否可以省略 一般情况下,是可以省略var的,但有两点值得注意: 1.var a=1 与 a=1 ,这两条语句一般情况下作用是一样的.但是前者不能用delete删除.不过,绝大多数情况下,这种差 ...
- JS中作用域和变量提升(hoisting)的深入理解
作用域(Scoping) javascript作用域之所以迷惑,是因为它程序语法本身长的像C家族的语言.我对作用域的理解是只会对某个范围产生作用,而不会对外产生影响的封闭空间.在这样的一些空间里,外部 ...
- 原型模式故事链(4)--JS执行上下文、变量提升、函数声明
上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...
- JS预解析与变量提升
预解析 JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的.JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程 预解析过程 ...
- JS中的 变量提升
首先纠正下,文章标题里的 “变量提升” 名词是随大流叫法,“变量提升” 改为 “标识符提升” 更准确.因为变量一般指使用 var 声明的标识符,JS 里使用 function 声明的标识符也存在提升( ...
- JS _函数作用域及变量提升
虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷)&g ...
- JavaScript中的各种变量提升(Hoisting)
首先纠正下,文章标题里的 “变量提升” 名词是随大流叫法,“变量提升” 改为 “标识符提升” 更准确.因为变量一般指使用 var 声明的标识符,JS 里使用 function 声明的标识符也存在提升( ...
- JavaScript中变量提升是语言设计缺陷
首先纠正下,文章标题里的 “变量提升” 名词是随大流叫法,“变量提升” 改为 “标识符提升” 更准确.因为变量一般指使用 var 声明的标识符,JS 里使用 function 声明的标识符也存在提升( ...
- javascript变量提升详解
js变量提升 对于大多数js开发者来说,变量提升可以说是一个非常常见的问题,但是可能很多人对其不是特别的了解.所以在此,我想来讲一讲. 先从一个简单的例子来入门: a = 2; var a; cons ...
随机推荐
- C++内联函数(C++ inline)详解
使用函数能够避免将相同代码重写多次的麻烦,还能减少可执行程序的体积,但也会带来程序运行时间上的开销. 函数调用在执行时,首先要在栈中为形参和局部变量分配存储空间,然后还要将实参的值复制给形参,接下来还 ...
- qt5 qmake开发
mkdir hello helloworld.cpp #include <QPushButton> #include <QApplication> int main(int a ...
- Win10登陆界面卡住,进去后无法打开网络相关的设置,谷歌浏览器无法上网
今天Win10抽风,进入登录页面输入用户名和密码之后,大约过了10分钟才进入桌面.重启后仍然如此. 经过调查,问题主要出在网络相关模块上,网络无法正常初始化,导致登录一直卡在网络初始化上. 解决方法如 ...
- 【Python】解析Python中的装饰器
python中的函数也是对象,函数可以被当作变量传递. 装饰器在python中功能非常强大,装饰器允许对原有函数行为进行扩展,而不用硬编码的方式,它提供了一种面向切面的访问方式. 装饰器 一个普通的装 ...
- config:fail,Error: 系统错误,错误码:63002,invalid signature [20191104 17:18:1
需要检查下后端有没有缓存到redis.这个很重要不然也会报这个错
- 005_Philippines之行准备
一.去前必备的手续 (1)SSP SSP(Special Study Permit),又叫特殊学生许可,是由菲律宾移民局要求的,每一位前往菲律宾进行游学的学生都要办理的一种特殊许可,学校会统一进行办理 ...
- Roberts算子
https://blog.csdn.net/likezhaobin/article/details/6892176 https://zhuanlan.zhihu.com/p/35032299 Robe ...
- 利用c# 多屏显示
公司搞了一个电视墙,要显示不同内容,于是买了一个多接口显卡(现在看来这个方案不是太好,但非常省钱) 要打开的就是几个网页,但要自己手工拖到不同电视上,非常麻烦 于是查了一下资料,发现可以用代码实现,说 ...
- Cassandra开发入门文档第五部分(使用场景)
正确建模 开发人员在构建Cassandra数据库时犯的另一个主要错误是分区键的选择不佳.cassandra是分布式的.这意味着您需要有一种方法来跨节点分布数据.Cassandra通过散列每个表的主键( ...
- SDKMAN一个基于命令行界面的SDK用户环境管理程序
1.背景 使用过Python开发的朋友,应该了解到Python2和Python3语法的差异,有时候从网上下载了基于不同解释器的代码,要来回切换版本, 使用起来不是很方便,有时候甚至很麻烦.于是有人发明 ...