Yfling

基础


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

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

Javascript里面的数据类型有哪些

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

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

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

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

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

{}{}? [][]? 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

函数有哪几种调用方式

直接调用
作为对象的方法调用
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)
}
或者用全局变量实现

```  

###面向对象

------------------------------------------

####原型与原型链
原型链是实现继承的主要方法,其基本原理是利用原型让一个引用继承另一个引用类型的属性和方法。
简单回顾一下构造函数,原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。我们让一个原型对象等于另一个类型的实例,此时原型对象将包含一个指向另一个原型的指针,另一个原型中也包含着指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是所谓原型链的基本概念


####js原型链的继承
####静态属性怎么继承
####js原型链以及特点 
因为每个对象和原型都有原型,对象的原型指向原型对象,
而父的原型又指向父的父,这种原型层层连接起来的就构成了原型链。
####面向对象有哪几个特点
封装,继承,多态  
####对象的继承
####创建对象的几种方式
####继承的两种方法
原型链继承和类继承。然后类继承只继承了实例属性,没有原型属性。
原型链继承可以继承所有。然后用apply和call怎么继承原型链上的共享属性?通过空函数传值。新建一个空函数C。C实例化后C的实例属性就是空,然后用B的apply/call去继承C,相当于继承了C的实例属性
####JS怎么实现继承
将父对象的一个实例赋值给子对象的原型 
[js实现继承的5种方式](http://javapolo.iteye.com/blog/1996871)
####new操作符时具体是干了些什么
New:
1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。
####怎么判断属性来自对象自身还是原型链
hasOwnProperty
####一个对象的实例,如何统计被几次调用过,分别具体被哪些函数调用过,可以有哪些方法
####写个Animal类
有个Cat类继承它,要求新建一个Cat的实例,可以调用catch方法输出自己的名字“大白的猫”;
####实现私有变量
(这里当时还没看到相关部分,只能想到用属性的setter、getter来做。。。

分类:

技术点:

相关文章: