1.引用变量赋值,内存分析,函数调用传参,运算符的优先级
预热一
var obj = {n: 1}
var obj2 = obj
obj2.n = 2
console.log(obj.n)
引用变量赋值问题
,答案为2
预热二
function fn1(a) {
a.n = 3
}
fn1(obj)
console.log(obj.n)
在函数内部里,把3 赋值给 obj 的成员n
,obj 为预热一的obj,所以答案为3
预热三
function fn2(a) {
a = {n:4}
}
fn2(obj)
console.log(obj.n)
上面的答案为 3
关于函数传参,堆里放的是局部的成员,a = {n:4}
是全局的成员,js解析器在分析js 的函数声明代码时,如果函数有带参数,实际上是在开始时加了一行代码:var 参数1,参数2...;即将参数隐性的声明为函数的局部变量,没有赋值
,在上面的例子中,a 为一个全局重新指向了一个引用。
注意:如果你还不是很理解,他加的一行代码,只是var 参数1 只是形参,如果实参赋值就是var 形参 = 实参。
如果不懂,小弟附上链接函数参数传递理解理解,望大侠海涵。
献上武功秘籍供武林豪杰参考
终极版–走向人生巅峰
var a = {n: 1}
var b = a
a.x = a = {n: 2}
# a.x = a = {n: 2} 赋值的时候,是从右往左传递赋值
# a.x = a = {n: 2} 但是有一个优先级的问题,a.x 的优先级的问题比= 号要高。
console.log(a.n, b.n) // ? ? 2 1
console.log(a.x, b.x) // ? ? undefined object{ n: 2}
深刻理解为什么?
作用域与作用域链,变量查找
<script type="text/javascript">
var x = 10
function fn() {
console.log(x)
}
function show(f) {
var x = 20
f()
}
show(fn) // ? 10
</script>
作用域查找先在自己上查找,没有在上面的作用域,知道全局作用域,一个函数一个作用域,所以x = 10
<script type="text/javascript">
// 全局作用域 -- 定义一个函数产生新的作用域 一个函数代表一个作用域,对象没有作用域
var fn = function () {
console.log(fn)
}
fn() // ? function定义
var obj = {
fn2: function () {
// 作用域查找问题, 先找fn2,找不到在全局找,然后就报错了
// console.log(fn2) obj.fn2() // ? 报错
// 想输出fn2属性的值
// 下面的代码解决了错误
console.log(this.fn2) // obj.fn2也行, 但比较死
}
}
obj.fn2() // ? 报错
</script>
变量提升,函数提升,预处理
- 预处理
- 收集用var声明变量
- 收集用function声明函数
- 函数与变量区别: 名=函数 名=非函数 名为变量
预热一
var a = 2
function fn() { // 预计处理:
/*
var a;
console.log(a)
a = 3
*/
console.log(a)
var a = 3
}
fn() // ? undefined 先在自己的作用域找
function fn2() { // 预计处理:
console.log(a)
a = 3 // a是全局变量
}
fn2() // ? 2
预热二 预计处理是变量先还是函数先? 直接记住 变量—>函数
function b() {
}
var b
console.log(typeof b) // ? // function
终极
/*
var c
function c(c) {
console.log(c)
var c = 3
}
c = 1
console.log(c) // 1 1看成函数调用就会报错,不可能执行函数体
c(2) //报错
*/
var c = 1
function c(c) {
console.log(c)
var c = 3
}
console.log(c) // ? 1
c(2) // ? 报错
作用域图
变量提升,IIFE,作用域与作用域链,变量查找
- 不推荐在if 里面定义变零
<script type="text/javascript">
var name = 'World!'
;(function () {
/*
var name
.....
*/
if (typeof name === 'undefined') {
var name = 'Jack' // var name var 提升
console.log(name) // jack
} else {
console.log(name)
}
})()
</script>
定时器,意外全局变量,作用域与作用域链,变量查找
<script type="text/javascript">
var a = 6
setTimeout(function () {
console.log(0)
alert(a)
a = 666
}, 0)
console.log(1) //1 和 0 谁先输出 1 ---- 0
a = 66
// 定时器是异步的,不管时间是0 还是其他,都是在主线程调用,代码执行的先后顺序,最后执行异步,所以答案是先弹出66
/*
1 , 0 ?
*/
</script>
DOM事件处理和闭包
- 需求: 点击某个按钮, 提示”第n个”
- 问题: 下面的实现代码是否正确, 如果不正确, 请正确实现
var btns = document.getElementsByTagName('button')
for(var i=0,length=btns.length;i<length;i++) { // i是一个全局变量, 遍历后是3
var btn = btns[i]
btn.onclick = function () {
alert('第'+(i+1)+'个')
}
}
正确实现
var btns = document.getElementsByTagName('button')
for(var i=0,length=btns.length;i<length;i++) { // i是一个全局变量, 遍历后是3
(function (i) {
var btn = btns[i]
btn.onclick = function () {
alert('第'+(i+1)+'个')
}
})(i) // 使用了闭包--->内存中产生了1+3个i
}
闭包的基本
function fn1() {
var a = 2
function fn2 () {
a++
console.log(a)
}
return fn2
}
var f = fn1()
f() // 3
f() // 4
this 闭包
<script type="text/javascript">
var name = "A"
var object = {
name: "B",
getNameFunc: function () {
return function () {
return this.name // this是谁? window
}
}
}
console.log(object.getNameFunc()()) //? A 函数调用,this 是window
var name2 = "A"
var object2 = {
name2: "B",
getNameFunc: function () {
var that = this // 缓存this ? object2 缓存this 的概念 对象调用函数的this 是对象
return function () {
return that.name2
}
}
}
console.log(object2.getNameFunc()()) //? B
</script>
原型与原型链,对象属性查找
<script type="text/javascript">
/*
测试题1
*/
function A () {
}
A.prototype.n = 1
var b = new A()
A.prototype = {
n: 2,
m: 3
}
var c = new A()
// 引用的问题
console.log(b.n, b.m, c.n, c.m) // ? ? ? ? 1 undefined 2 3
</script>
原型与原型链,实例对象,构造函数,Object, Function的关系
<script type="text/javascript">
var F = function(){}
Object.prototype.a = function(){
console.log('a()')
}
Function.prototype.b = function(){
console.log('b()')
}
var f = new F()
F.a() // ? a()
F.b() // ? b()
f.a() // ? c()
f.b() // ? f 是一个实例对象,他的原型有object, 没有Function 报错:f.b() 不是一个函数
</script>
原型图
变量提升,this,运算符优先级,原型与原型链,全局变量污染
<script type="text/javascript">
function Person() {
getAge = function () {
console.log(10)
}
return this
}
Person.getAge = function () {
console.log(20)
}
Person.prototype.getAge = function () {
console.log(30)
}
var getAge = function () {
console.log(40)
}
function getAge() {
console.log(50)
}
Person.getAge() // ? 20
getAge() // ? 40
Person().getAge() // ? 10
getAge() // ? 10
new Person.getAge() // ? 20
new Person().getAge() // ? 30
</script>