JS汇总---基础&函数&闭包

基础


Javascript是一种弱类型语言,它分别有什么优点和缺点

弱类型语言:简单好用,更灵活多变。但是会牺牲性能,比如一些隐含的类型转换
强类型语言:类型转换的时候非常严格,,强类型语言是直接操纵内存,容易出内存越界和泄漏的问题。在类型的转换方面是很多约束,甚至强制转换也要很谨慎,一不小心就出大问题。

Javascript里面的数据类型有哪些

5个简单数据类型(基本数据类型)+ 1个复杂数据类型
undefiend, number string null boolean + object

有几种方式可以判断数据类型

typeof和intanceof
其实typeof和instanceof的目的都是检测变量的类型,两个的区别在于typeof一般是检测的是基本数据类型,instanceof主要检测的是引用类型!

typeof.png

基本类型和引用类型有什么区别

赋值的时候基本类型按值,引用类型按引用,就是基本类型会复制一份,引用类型就是一个新的指针
函数传参的时候都是按值传递

{}=={}? []==[]? null==undefined?

{}=={}()
[]==[]()
null == undefined(对)

写个方法判断一个变量的类型

函数


函数声明和函数表达式有什么区别

函数声明会将那个函数提升到最前面,成为全局函数。函数声明要指定函数名,而函数表达式不用,可以用作匿名函数。
创建函数的方式:函数声明函数表达式、还有一种不常见的方式就是Function构造器
函数声明:

function add(a,b) {
    a = +a;
    b = +b;
    if (isNaN(a) || isNaN(b)) {
        return;
    }
    return a + b;
}

函数表达式的几种方式:

// 函数表达式
var add = function(a, b) {
    // do sth
}


// 匿名函数定义的一个立即执行函数表达式
(function() {
    // do sth
})();


// 作为返回值的函数表达式
return function() {
    // do sth
};


// 命名式函数表达式
var add = function foo (a, b) {
    // do sth
}

函数声明与函数表达式的主要区别就是:函数声明会被前置
函数声明前置:

// function add(a,b) 已经声明前置了,可以正常调用
var num = add(1, 2);
console.log(num);  // 3

function add(a,b) {
    a = +a;
    b = +b;
    if (isNaN(a) || isNaN(b)) {
        return;
    }
    return a + b;
}

函数表达式前置:

// var add 变量声明提前,此时变量的值是undefined
var num = add(1, 2);
console.log(num);  // TypeError:undefined is not a function

var add = function(a, b) {
    a = +a;
    b = +b;
    if (isNaN(a) || isNaN(b)) {
        return;
    }
    return a + b;
}

Function构造器:

var func = new Function('a', 'b', 'console.log(a+b);');
fun(1, 2); // 3

// 和上面的方式没有区别
var func = Function('a', 'b', 'console.log(a+b);');
func(1, 2); // 3

区别:


360截图20170307114742162.png

原型与原型链

每一个构造函数都有一个prototype,指向一个对象,这个对象的所有属性和方法,都会被构造函数的实例继承。
原型链作为实现继承的主要方法。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
在JavaScript中,用proto 属性来表示一个对象的原型链。当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止!

函数有哪几种调用方式

直接调用
作为对象的方法调用
apply,call

作用域

JS没有块作用域,只有函数作用域
作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的。

作用域链是什么

A://说的不是很清楚

闭包

闭包是什么

闭包是指有权访问另一个函数作用域中的变量的函数

创建闭包的方式:
在一个函数内部创建另一个函数

闭包的作用:
1.让这些函数的值始终保存在内存中

滥用闭包有什么副作用

由于闭包会携带包含它的函数的作用域链,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,所以只在绝对必要时使用闭包。

闭包实现块级作用域

(function() {

})();

闭包的作用/应用

匿名自执行函数、缓存、实现封装(主要作用)、实现面向对象中的对象
1 匿名自执行函数

我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,
比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。
除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,
比如UI的初始化,那么我们可以使用闭包:

var datamodel = {    
    table : [],    
    tree : {}    
};    
     
(function(dm){    
    for(var i = 0; i < dm.table.rows; i++){    
       var row = dm.table.rows[i];    
       for(var j = 0; j < row.cells; i++){    
           drawCell(i, j);    
       }    
    }    
       
    //build dm.tree      
})(datamodel);   
```
我们创建了一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在执行完后很快就会被释放,关键是这种机制不会污染全局对象。

**2缓存**

再来看一个例子,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
```
var CachedSearchBox = (function(){    
    var cache = {},    
       count = [];    
    return {    
       attachSearchBox : function(dsid){    
           if(dsid in cache){//如果结果在缓存中    
              return cache[dsid];//直接返回缓存中的对象    
           }    
           var fsb = new uikit.webctrl.SearchBox(dsid);//新建    
           cache[dsid] = fsb;//更新缓存    
           if(count.length > 100){//保正缓存的大小<=100    
              delete cache[count.shift()];    
           }    
           return fsb;          
       },    
     
       clearSearchBox : function(dsid){    
           if(dsid in cache){    
              cache[dsid].clearSelection();      
           }    
       }    
    };    
})();    
     
CachedSearchBox.attachSearchBox("input1");    
```
这样,当我们第二次调用CachedSearchBox.attachSerachBox(“input1”)的时候,我们就可以从缓存中取道该对象,而不用再去创建一个新的searchbox对象。

**3 实现封装**

可以先来看一个关于封装的例子,在person之外的地方无法访问其内部的变量,而通过提供闭包的形式来访问:
```
var person = function(){    
    //变量作用域为函数内部,外部无法访问    
    var name = "default";       
       
    return {    
       getName : function(){    
           return name;    
       },    
       setName : function(newName){    
           name = newName;    
       }    
    }    
}();    
     
print(person.name);//直接访问,结果为undefined    
print(person.getName());    
person.setName("abruzzi");    
print(person.getName());    
   
得到结果如下:  
   
undefined  
default  
abruzzi  
```
4 **实现面向对象中的对象**
传统的对象语言都提供类的模板机制,这样不同的对象(类的实例)拥有独立的成员及状态,互不干涉。虽然JavaScript中没有类这样的机制,但是通过使用闭包,我们可以模拟出这样的机制。还是以上边的例子来讲:
```
function Person(){    
    var name = "default";       
       
    return {    
       getName : function(){    
           return name;    
       },    
       setName : function(newName){    
           name = newName;    
       }    
    }    
};    
     
     
var john = Person();    
print(john.getName());    
john.setName("john");    
print(john.getName());    
     
var jack = Person();    
print(jack.getName());    
jack.setName("jack");    
print(jack.getName());    
   
运行结果如下:  
   
default  
john  
default  
jack  
```
由此代码可知,john和jack都可以称为是Person这个类的实例,因为这两个实例对name这个成员的访问是独立的,互不影响的。

####实现一个暴露内部变量,而且外部可以访问修改的函数
(get和set,闭包实现) 
```
var person = function(){    
    //变量作用域为函数内部,外部无法访问    
    var name = "default";       
       
    return {    
       getName : function(){    
           return name;    
       },    
       setName : function(newName){    
           name = newName;    
       }    
    }    
}();    
     
print(person.name);//直接访问,结果为undefined    
print(person.getName());    
person.setName("abruzzi");    
print(person.getName());    
   
得到结果如下:  
   
undefined  
default  
abruzzi  
```


####从几个li中取下标的闭包代码
```
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>


var li=document.getElementsByTagName("li");

for(var i=0;i<li.length;i++) {
    (function(x) {
        li[x].onclick=function(){alert(x);}
    })(i);
}

```
####实现一个闭包的例子(实现了一个定时函数传值的)
```
闭包:
for(var i = 0; i < 10; i++ ){
    (function(x){
        setTimeout(function(){
            console.log(x)
        },x*1000)
    })(i)
}
或者用全局变量实现

```
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容