********************************************************************
总结过一次,再总结一下,思路会清晰很多。
一、闭包
内部方法使用外部方法的变量(下面图很好的展示对应关系)
两个方法指向的变量是同一个,外部的方法销毁,但却把内部方法返回(变量一直存在)
作用域
Activation Object (上下文环境作用域,简称AO)
Global Object (全局作用域,简称GO)
举个闭包的例子:
function add(){
var i=0;
function x(){
i++;
}
return x;
}
条件:基本方法包含一个到多个内部方法;最后把内部方法return出来
立即执行函数,只执行一次(立即执行---())
(function(){
}())
(function(){
})()
例题
var x=1;
if(function f(){}){
x+= typeof f;
}
console.log(x);
打印结果?
知识点:
if()中会自动转变成语句,而function f(){}则是未声明的语句 是undefined
typeof会返回字符串类型
所以结果是:1undefined
面试题一
function test(){
var x=[]
for(var i=0;i<10;i++){
x[i]=function(){
console.log(i);
}
}
return x;
}
test();
本意:想打印从0~9 10个数,但结果却不是。匿名函数中并没有定义i。所以他是找不到i这个变量的,需要到外部函数找i,等到找到i的时候,循环结束。返回的是最终的结果
解决方案
function test(){
var x=[]
for(var i=0;i<10;i++){
x[i]=(function(j){
console.log(j);
})(i)
}
return x;
}
test();
加入()立即执行(function(j){return j})(i) i--实参 j--形参
面试题二
抛出问题:
此题的目的是想每次点击对应目标时弹出对应的数字下标 0~4,但实际是无论点击哪个目标都会弹出数字5
问题所在:
arr 中的每一项的 onclick 均为一个函数实例(Function 对象),这个函数实例也产生了一个闭包域,这
个闭包域引用了外部闭包域的变量,其 function scope 的 closure 对象有个名为 i 的引用,外部闭包
域的私有变量内容发生变化,内部闭包域得到的值自然会发生改变
function onMyLoad(){
var arr = document.getElementsByTagName("p");
for(var i = 0; i < arr.length;i++){
arr[i].onclick = function(){
alert(i);
}
}
}
<body onload="onMyLoad()">
<p>产品一</p>
<p>产品二</p>
<p>产品三</p>
<p>产品四</p>
<p>产品五</p>
</body>
解决
function onMyLoad(){
var arr = document.getElementsByTagName("p");
for(var i = 0; i < arr.length;i++){
(function(args){
arr[i].onclick = function(){
alert(args);
}
})(i)
}
}
function onMyLoad(){
var arr = document.getElementsByTagName("p");
for(var i = 0; i < arr.length;i++){
arr[i].onclick = (function(args){
return function(){
alert(args);
}
})(i)
}
}
可以试一下
二、预编译
预编译引申出两个概念AO(局部变量)和GO(全局变量)
函数声明整体提升
变量 声明提升
预编译前奏
1.暗示全局变量:即任何变量 如未经声明,则变为全局对象
2.一切声明的全局变量,都是window的属性
预编译的四步
1.将var x;提出来 并赋予undefined
2.将实参赋予
3.将 function y(){}提出来 赋予undefined
4.编译
环境的话 先执行GO,再执行AO,在AO找不到就会扩大作用域到GO去找
三、运算符
1/0 --->infinity正无穷
NAN --->not a number
优先级
‘=’最弱,‘()’最强
四、作用域
每一个函数就是一个对象,对象中有些属性是可以访问的,有些则是不可以访问的。
[[scope]]就是其中一个,其是--作用域
同一个对象的AO都是独一无二的,用完即销毁。但[[scope]]却存了执行上下文的集合(作用域链)。
在查找作用域链的时候 从 顶端从下开始查找
例: var a=123;
function test(){
var a=234;
console.log('a')
}
test()
此时打印出来的就是234,那么为什么不是123,这里就涉及到一个作用域链的问题。
五、原型
原型是对象的一个属性,他是对象共有的属性,通过该原型产生的对象会继承该属性或方法。原型也是对象。
隐式对象:__proto__
添加属性名字:prototype
例如:xx.prototype.name='lina' 就给xx对象添加了一个隐式的name属性。他是共有的
原型链
在对象中,有隐式变量。如果父对象中的子对象有隐式变量。可以访问到子对象的隐式变量。这样就形成了原型链。
但最后的终点是Object.访问Object的原型是null.
************************持续更新**********************************