javascript梳理

253 阅读1分钟

面试时经常遇到的一些javascript问题,在此整理下,也是对于知识的梳理

1.闭包(老生常谈)

可以这样理解:闭包是定义在一个函数内部的函数,

用于封闭变量比如
(function(){
var a=1;
alert(a);
})();//这就是一个闭包,它执行不会为外部添加全局变量,也就是不会对外部产生影响

其实jq中使用了大量的闭包,所有的方法和变量都通过闭包设为私有,并使用$在全局进行调用。闭包就是使局部变量和方法常驻内存,可以在全局进行访问,从而防止全局重名的现象。不过也正因为这个特性,闭包会占用大量的内存空间,所以使用的时候也要慎重。

2.构造函数,原型,原型链

(1)先从构造函数讲起

function Foo(){};
var f1 = new Foo();
构造函数:用来初始化新创建的对象的函数就是构造函数,在例子中Foo()就是构造函数

(2)实例对象

 通过构造函数的new操作创建的对象就是实例对象,可以用一个构造函数创建多个实例对象
 function Foo(){};
 var f1 = new Foo();
 var f2 = new Foo();
 console.log(f1===f2)//false
 

(3)原型及prototype

构造函数有一个prototype属性,指向实例对象的原型对象,通过同一个构造函数
实例化的多个对象具有相同的原型对象,经常使用原型对象来实现继承
function Foo(){};
Foo.prototype.a = 1;
var f1 = new Foo();
var f2 = new FOO();
console.log(Foo.prototype.a)//1;
console.log(f1.a)//1;
console.log(f2.a)//1

(4)constructor属性

原型对象上有一个constructor属性,指向该原型对象对应的构造函数
function Foo(){};
console.log(Foo.prototype.constructor === FOO)

由于实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,指向原型对象对应的构造函数

function Foo(){};
var f1 = new Foo();
console.log(f1.constructor === Foo)//true

(5)proto属性

实例对象有一个--proto--属性,指向该实例对象对应的原型对象
function Foo(){};
var f1 = new Foo();
console.log(f1.--proto--==Foo.prototype)//true

实例对象的--proto--属性指向原型对象,通过--proto--属性构成的链式关系叫做原型链

3.函数中的(this)

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};

this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以,this.birth可以拿到xiaoming的birth属性

3.数组

1.首先从创建数组开始:

在JavaScript中创建数组有两种方式如下所

(一)使用 Array 构造函数:

var arr1 = new Array(); //创建一个空数组
var arr2 = new Array(20); // 创建一个包含20项的数组
var arr3 = new Array("lily","lucy","Tom"); // 创建一个包含3个字符串的数组

(二)使用数组字面量表示法:

var arr4 = []; //创建一个空数组
var arr5 = [20]; // 创建一个包含1项的数组
var arr6 = ["lily","lucy","Tom"]; // 创建一个包含3个字符串的数组

2.数组的内建方法

1、join()

join(separator): 将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符

var arr = ['A','B','C','D'];
console.log(arr.join()); // A,B,C,D
console.log(arr.join("-")); // A-B-C-D
console.log(arr); // ['A','B','C','D'](原数组不变)

2.indexOf()

搜索一个指定的元素的位置

var arr = ['A','B','C','D'];
arr.indexOf('C');//2
arr.indexOf('d');//-1,不存在返回-1
3.slice()

截取数组的长度然后返回新的数组

var arr = ['A','B','C','D'];
arr.slice(0,3);//从开始索引0开始,到结束索引结束,但不包括结束索引,['A','B','C']
arr.slice(3);//从3开始到结束,['D']
4.push()

数组尾部添加若干内容

var arr = ['A','B','C','D'];
arr.push('J');//['A','B','C','D','J']
5.pop()

删除数组尾部最后一个元素

var arr = ['A','B','C','D'];
arr.pop()//['A','B','C']
5.unshift()

向数组头部添加若干内容

var arr = ['A','B','C','D'];
arr.unshift('J','K');//['J','K','A','B','C','D']
5.shift()

删除数组的第一个元素

arr.shift();arr.shift();arr.shift();//连续删除3次
7.sort()

给数组排序

var arr = ['1','100','10','52','845']
arr.sort();
arr;//1,10,100,52,845
8.reverse()

给数组倒序

var arr = ['A','B','C','D'];
arr.reverse();//['D','C','B','A']
9.concat()

把当前的数组和另一个数组合并为一个新的数组

var arr = ['A','B','C','D'];
var arr2 = [1,2,3]
arr.concat(arr2);//['A','B','C','D',1,2,3],arr并没有被修改
10.splice()

从指定的索引开始向数组中添加或者删除元素

arr.splice(1,3,'E','F');//删除+添加,返回删除的元素['B','C','D']
arr;//['A','E','F']
arr.splice(1,3);//只删除,不添加,返回翻出的元素['B','C','D']
arr;//['A']
arr.splice(2,0,'E','F','G');//返回[],因为没有删除任何元素
arr;//['A','B','C','D','E','F','G']

数组内建的发布有时不能满足我们的需求时,我们需要扩展数组的方法 如数组去重:

思路: 1)构建一个新的数组存放结果;
      2)for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比;
      3)若结果数组中没有该元素,则存到结果数组中。

Array.prototype.unique1 = function(){  
        var res = [this[0]];  
        for(var i = 1; i < this.length; i++){  
            var repeat = false;  
            for(var j = 0; j < res.length; j++){  
                if(this[i] == res[j]){  
                    repeat= true;  
                    break;  
                }  
            }  
            if(!repeat){  
                res.push(this[i]);  
            }  
        }  
        return res;  
    }  
    var arrNum2 = [1,4,1,1,3,3,4,6,7,8,3,7,0,2,11,2,2,22,11,22];  
    console.log(arrNum2.unique1());  

数组去重这里再加上一个方法

遍历将数组的值添加到一个对象的属性名里,并给属性赋值,对象不能添加相同的属性名,依据这个可以实现数组的去重,然后用Object.keys(对象)返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组

let a = ['1','2','3','3',NaN,undefined,undefined,'a','b','c'];
const unique = arr =>{
    var obj = {}
    arr.forEach(value =>{
        obj[value] = 0
    })
    return Object.keys(obj)
}
console.log(unqiue(a))//['1','2','3','NaN','undefined','a','b','c']

4.字符串

String对象属性

(1)length属性

length算是字符串非常常用的属性了,它的功能是获取字符串的长度,当然需要注意的是js中的中文每个汉字也只能代表一个字符

var str = 'abc';
console.log(str.length);//3

(2)prototype属性

prototype在面向对象编程中经常使用到,用来给对象添加属性或方法,并且添加的方法或属性在所有的实例上共享,因此也常用来扩展js内置对象,如下面的代码给字符串添加了一个去除两边空格的方法

String.prototype.trim = function(){
    return this.replace(/^\s*|\s*$/g, '')
}

String对象方法 获取类方法 (1)charAt()用来制定位置的字符串,index为字符串索引值,从0开始到string.length-1,若不在这个范围将返回一个空字符串

stringObject.charAt(index)
var str = 'abcde'
console.log(str.charAt(2))// 返回c
console.log(str.charAt(8))//返回空字符串

截取类方法

(1)substring()
stringObject.substring(start,end)

substring()是最常用的字符串截取方法,它可以截取两个参数(参数不能为负值),分别是要截取的开始位置和结束位置,它将返回一个新的字符串,其内容是从start处到end-1处的字符,若截取参数(end)省略,则表示从start位置一直截取到最后 var str = 'abcdefghj'; console.log(str.substring(1,4));//返回bcd console.log(str.substring(1));//返回bcdefg console.log(str.substring(-1))//返回abcdefghj,传入负值时会视为0

split()方法

split()方法用于把一个字符串分割成字符串数组,第一个参数separator表示分割位置(参考符),第二个参数表示返回数组的允许最大长度

var str = 'a|b|c|d|e';
console.log(str.split('|'));//返回["a","b","c","d","e"]
console.log(str.split('|',3));//返回["a","b","c"]
console.log(str.split(''));//返回["a", "|", "b", "|", "c", "|", "d", "|", "e"]