javascript基础

117 阅读5分钟

===与==

== 自动转换数据类型再比较; === 不转换类型 (更好) 例外: NaN === NaN // false

字符串

使用反引号来表示多行字符串

var a = `这是一个
多行
字符串`;

字符串不可变:使用a[0] = 'X'并没有改变效果

数组

直接给array的length赋新值会改变Array的大小; length变大则新增元素为undefined;变小则删除超出长度的元素;

数组方法

slice   // 不加参数可以用于复制数组,不改变本身
pop
push
unshift // 在头部添加
shift   // 在头部删除
sort    // 字母排序
reverse // 反转
splice  // 从指定索引删除若干元素,在从该位置添加若干元素
concat  // 拼接,返回新Array
join    // 使用指定字符拼接数组元素 ==> String

Map 键值对结构,大数据量时具有极快的查找速度

根据key值迅速获取对应value

var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

Set 只有非重复key,没有value值

var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}
// 添加元素
s.add(4);
s; // {1, 2, 3, 4}
// 删除元素
s.delete(3);

iterable类型

包括Array、Map、Set等; for。。。in 循环对象的属性名称key;一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性。 for。。。of 循环对象键值对中的value;更适合遍历没有key的集合,如Set; forEach方法 (更好)

a.forEach(function (element, index, array) {
    // element: 指向当前元素的值
    // index: 指向当前索引
    // array: 指向Array对象本身
    alert(element);
});
​
// Set与Array类似,但Set没有索引,因此回调函数的前两个参数都是元素本身:
// Map的回调函数参数依次为value、key和map本身:

函数arguments参数

它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array: 利用arguments,你可以获得调用者传入的所有参数。即使函数不定义任何参数,还是可以拿到参数的值

当传入参数个数超过函数定义的参数个数,则将多余参数传入rest参数。

// rest参数只能写在最后,前面用...标识
// 传入的参数先绑定a、b,多余的参数以数组形式交给变量rest
// 所以,不再需要arguments我们就获取了全部参数。
function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
}
​
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]foo(1);
// 结果:
// a = 1
// b = undefined
// Array []

全局对象 window

全局作用域的变量实际绑定到window的一个属性

'use strict';
​
var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript'// 全局变量course 等同于 window.course
// alert函数也是window的一个变量

减少全局变量的冲突:声明一个唯一的全局变量{};然后把所有变量和函数都绑定到这个唯一一个全局变量上。

局部作用域

for循环中,var i可以在循环块外部被引用;ES6的let i则解决了这个问题。

'use strict';
​
function foo() {
    for (var i=0; i<100; i++) {
        //
    }
    i += 100;      // 仍然可以引用变量i
}
​
​
'use strict';
​
function foo() {
    var sum = 0;
    for (let i=0; i<100; i++) {
        sum += i;
    }
    i += 1;       // SyntaxError
}

this丢失问题

对象方法中的this,必须由对象进行调用该方法才能获取this; 对象方法中的函数,this指向全局对象window; 解决方法1: that

// 保存当前this  ===> that
'use strict';
​
var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var that = this; // 在方法内部一开始就捕获this
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - that.birth; // 用that而不是this
        }
        return getAgeFromBirth();
    }
};
​
xiaoming.age(); // 25

解决方法2: apply与call

// 使用apply或call,控制函数的this指向传入的首个参数
function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}
​
var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};
​
xiaoming.age(); // 25// apply()把参数打包成Array再传入;
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
// 把参数按顺序传入。
getAge.call(xiaoming)

解决方法3: IFEE思想,bind(this)

高阶函数

函数参数`指向`函数

map逐一映射

// *****
// “把f(x)作用在Array的每一个元素并把结果生成一个新的Array”。
// *****
function pow(x) {
    return x * x;
}
​
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]

reduce瀑布映射

原理:[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

// *****
// 把结果继续和序列的下一个元素做累积计算
// *****// [1, 3, 5, 7, 9]变换成整数13579,reduce()也能派上用场:var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
    return x * 10 + y;
}); // 13579

filter过滤

filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。

// 利用filter,可以巧妙地去除Array的重复元素:'use strict';
​
var r,
    arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
​
r = arr.filter(function (element, index, self) {
    // indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,被过滤
    return self.indexOf(element) === index;
});
​
alert(r.toString());

sort 排序

sort()方法会直接对Array进行修改,它返回的结果仍是当前Array: 默认把所有元素先转换为String再排序,字符串根据首个字符的ASCII码进行排序 sort的自定义排序中,return -1不对调;return 1对调;

// 升序排列
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return -1;
    }
    if (x > y) {
        return 1;
    }
    return 0;
}); // [1, 2, 10, 20]

箭头函数

x => x * x   
​
等同于  
​
function (x) {
    return x * x;
}

箭头函数相当于匿名函数 格式一,只包含一个表达式,可以省略{ ... }和return 格式二,包含多条语句,不能省略{ ... }和return:

参数

// 两个参数:
(x, y) => x * x + y * y
​
// 无参数:
() => 3.14
​
// 可变参数:
(x, y, ...rest) => {
    var i, sum = x + y;
    for (i=0; i<rest.length; i++) {
        sum += rest[i];
    }
    return sum;
}

返回对象

返回对象时存在语法冲突{} 所以改为({foo:x})

this作用域

箭头函数修复了this的指向,this总是指向词法作用域,也就是外层调用者obj: 也就是说,在对象(第一层)的方法(第二层)的函数(第三层)中,仍然可以用this调用到对象的属性值;

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => new Date().getFullYear() - this.birth;    //this指向obj对象
        return fn();
    }
};
obj.getAge(); // 25

call()与apply()

由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略,直接传入参数即可

var obj = {
    birth: 1990,
    getAge: function (year) {
        var b = this.birth; // 1990
        var fn = (y) => y - this.birth; // this.birth仍是1990
        return fn.call({birth:2000}, year);
        // 原本需要写作fn.call(this, {birth:2000}, year)
    }
};
obj.getAge(2015); // 25