当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。
闭包小例子:
function a(){
var num = 100;
function b(){
num ++;
console.log(num);
}
return b;//或者demo = b;
}
//a 的AO被销毁
var demo = a(); //执行a,将函数b保存在demo中
demo(); //执行b,打印出101
//此时a的AO已经被销毁,第一次执行完b之后,将a的AO里面num值改为101,b的AO被销毁
demo(); //再执行b,打印出102
1、实现公有变量
eg : 函数累加器
function add(){
var count = 0;
function demo(){
count ++;
sonsole.log(count);
}
return demo();
}
var counter = add();
counter();
counter();
counter();
function test(){
var num = 100;
function a(){
num ++;
console.log(num);
}
function b(){
num --;
console.log(num);
}
return [a,b];
}
var myArr = test();
myArr[0](); //打印101
myArr[1]{}; //打印100
//a和b共用一个test的AO
2、可以做缓存(存储结构)
eg : eater
function eater(){
var food = "";
var obj = {
eat : function (){
console.log("i am eating" + food);
food = "";
}, //对象的方法
push : function(myFood){
food = myFood;
}
}
return obj;
}
var eater1 = eater();
eater1.push('banana');
eater1.eat();
3、可以实现封装,属性私有化
eg : Person();
4、模块化开发,防止污染全局变量
闭包会导致多个执行函数共用一个公有变量,如果不是特殊需要,应尽量防止这种情况发生。
function test(){
var arr = [];
for (var i = 0; i < 10; i ++){
arr[i] = function (){
document.write(i + " ");
}//执行test函数时并不执行里面这个函数体,
}//循环到i = 10;跳出循环
return arr;
}
var myArr = test();//先执行完test函数,此时i = 10;
for(var j = 0; j < 10; j ++){
mrArr[j]();//此时才执行function (){document.write(i + "");}
}
//程序结果打印十个10
解决方法:利用立即执行函数的特性
function test(){
var arr = [];
for(var i = 0; i < 10; i ++){
(function (j){
arr[j] = function (){
document.write(j + " ");
}
}(i));//立即执行函数是读到它的时候就执行,不需要先调用
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j ++){
myArr[j]();
}
试题1:无序列表,使用原生JS, addEventListener,给每个li元素绑定一个click事件,输出他们的顺序
function test(){
var liCollection = document.getElementByTagName('li');
for(var i = 0; i < liCollection.length; i++){
(function (j){
liCollection[j].onclick = function(){ //把函数绑定到了每个li元素(外部)
console.log(i);
//console.log(this.innerText);点击打印li元素里的内容
}
}(i))
}
}
test();
定义和用法:
charCodeAt()方法可返回指定位置的字符的Unicode编码。这个返回值是0-65535之间的整数。(当返回值是 <=255 时,为英文;当返回值 >255 时为中文、日文等非常规字符)。
charCodeAt() 与 charAt() 方法执行的操作相似,只不过前者返回的是位于指定位置的字符的编码,而后者返回的是字符子串。
语法:
stringObject.charCodeAt(index)
index 必需。表示字符串中某个位置的数字,即字符在字符串中的下标,从0开始。负数或大于字符串长度时返回NaN;
eg:
<script type="javascript/text">
var str = "Hello world!"
document.write(str.charCodeAt(1)); //输出101
</script>
试题2:写一个方法,求一个字符串的字节长度。(提示:字符串有一个方法 charCodeAt(); 一个中文占两个字节,一个英文占一个字节)
function retByteslen(target){
var count = 0;
for(var i = 0; i < target.length; i++){
if(target.charCodeAt(i) <= 255){
count ++;
}else if(target.charCodeAt(i) > 255){
count += 2;
}
}
console.log(count);
}
//简化
function retByteslen(target){
var count,len;
count = len = target.length;
for(var i = 0; i < len; i++){
if(target.charCodeAt(i) > 255){
count ++;
}
}
console.log(count);
}
试题3:写出下列程序的执行结果
var f = (
function f(){
return "1";
},
function g(){
return 2;
}
)();
console.log(typeof f); //number
//var a=(2,3); a的值为3
//先计算逗号前的表达式,在计算逗号后面的表达式,最后返回逗号后面表达式的结果
试题4:写出下列程序的执行结果
var x = 1;
if(function f() {}){ //(function f() {})在括号中,变成表达式,不是函数定义,f消失
x += typeof f; //未经声明的变量f只有在typeof里面不报错,返回string类型的undefined
//1 + undefined(undefined类型) 结果为 NaN
}
console.log(x); //1undefined
作业:
1、运行 test() 和 new test() 的结果分别是什么?
var a = 5;
function test(){
a = 0;
alert(a);
alert(this.a);
var a;
alert(a);
}
2、分析下面的JavaScript代码段
function employee(name,code){
this.name = "wangli";
this.code = "A001";
}
var newemp = new employee("zhangming",'A002');
document.write("雇员姓名:"+ newemp.name+"
");
document.write("雇员代号:"+ newemp.code+"
");
输出结果是(A).(单选)
A.雇员姓名:wangli 雇员代号:A001
B.雇员姓名:zhangming 雇员代号:A002
C.雇员姓名:null 雇员代号:null
D.代码有错误,无输出结果
3、a = 100;
function demo(e){
function e(){}
arguments[0] = 2; //第一个形参值赋2
document.write(e); //打印2
if(a){ //现在不允许在if中定义函数(题中假设允许)
var b = 123;
function c(){
//
}
}
var c;
a = 10;
var a;
document.write(b); //打印undefined
f = 123;
document.write(c); //打印function c(){}
document.write(a); //打印10
}
var a;
demo(1);
document.write(a); //打印100
document.write(f); //打印123
4、var str = "abc";
str += 1;
var test = typeof(str);
if(test.length == 6){
test.sign = "typeof的返回结果可能为String";
}
document.write(test.sign);//undefined
5、function Person(name, age, sex){
var a = 0;
this.name = name;
this.age = age;
this.sex = sex;
function sss(){
a ++;
document.write(a);
}
this.say = sss;
}
var oPerson = new Person();
oPerson.say();//1
oPerson.say();//2
var oPerson1 = new Person();
oPerson1.say();//1
6、改为可以输出0-9的形式
function bb(){
var arr = [];
for(var i = 0; i < 10; i++){
arr[i] = function(){
document.write(i);
}
}
return arr;
}
var arr1 = bb();
for(var i = 0; i < 10; i++){
arr1[i]();
}
7、var str = false + 1;
document.write(str);
vae demo = false == 1;
document.write(demo);
if(typeof(a)&&-true + (undefined) + ""){
document.write('基础扎实');
}
if(11 + "11" * 2 ==33){
document.write('基础扎实');
}
!!" " + !!"" - false||document.write('emmmm');