JavaScript 学习笔记(一)

shift() 用法

1
2
3
4
5
var arr = new Array(1,2,3);
console.info(arr.shift()); //输出: 1
console.info(arr);//输出: [2,3]
arr.push(4);
console.info(arr);//输出: [2,3,4]

call

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Product(name,price){
this.name = name;
this.price = price;
if(price<0){
throw RangeError("Cannot create product " +
this.name + " with a negative price");
}
}
function Food(name,price){
Product.call(this,name,price);
this.category = "food";
}
function Toy(name,price){
Product.apply(this,[name,price]);
this.category = "toy";
}
var apple = new Food("apple" ,7);
var toy = new Toy("tank",25);
console.info(apple);
console.debug(toy);

使用call方法调用匿名函数

1
2
3
4
5
6
7
8
9
10
11
12
13
var animals = [
{species: 'Lion', name: 'King'},
{species: 'Whale', name: 'Fail'}
];
for (var i = 0; i < animals.length; i++) {
(function (i) {
this.print = function () {
console.log('#' + i + ' ' + this.species + ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}

proto

1
2
3
4
5
6
7
8
9
function Person(name){
this.name = name;
}
var alice = new Person("alice");
var jake = Object.create(alice);
console.info(alice.name);
console.info(alice.name);
console.info(alice == jake);//fale
console.info(jake.__proto__ === alice);//true

call , applay

1
2
3
4
5
6
7
8
9
var ShowName = function(){
console.info(this.name);
}
var peter = {
name:"peter"
}
ShowName.call(peter);
ShowName.apply(peter,[]);

JavaScript给对象提供了一个名为proto的隐藏属性,某个对象的proto属性 默认会指向它的构造器的原型对象,即{Constructor}.prototype。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Person( name ){
this.name = name;
};
Person.prototype.getName = function(){
return this.name;
};
var objectFactory = function(){
var obj = new Object();
var Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype; //obj.__proto__ = Person.prototype;
Constructor.apply(obj,arguments);
return obj;
};
var alice = objectFactory(Person,"alice");
var jhon = new Person("jhon");
console.debug(alice);
console.debug(jhon);

class

ECMAScript 6带来了新的Class语法。这让JavaScript看起来像是一门基于类的语 言,但其背后仍是通过原型机制来创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Animal{
constructor(name){
this.name = name;
}
}
class Dog extends Animal{
//可缺省
constructor(name){
super(name);
}
speak(){
return "woof";
}
}
var dog = new Dog("Scamp");
console.info(dog.name + " , say: " + dog.speak());

实现 Function.prototype.bind

1
2
3
4
5
6
7
8
9
10
11
12
Function.prototype.bind = function(context){
var self = this;
var ret = function(){
self.apply(context,arguments);
}
return ret;
};
var obj = {name:"alice"};
var showName = function(){
console.info(this.name);
}.bind(obj);
showName();

分2次传递参数,使用 strict this.name = undifined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//'use strict'
//'use strict'
Function.prototype.bind = function(){
var self = this;
var context = [].shift.call(arguments);
var args = [].slice.call(arguments);
return function(){
var args2 = [].slice.call(arguments);
return self.apply(context,
[].concat.call(args,args2 )
);
}
};
var obj = {name:"sven"};
var func =function(a,b,c,d){
console.info("this.name = " + this.name );
console.info([a,b,c,d]);
}.bind(obj,1,2);
func(3,4);

forEach ES5.1 引入

1
2
3
4
5
var a =['A','B','C'];
a.name = "Alice";
a.forEach(function(element,index,array){
console.info(`el = ${element} , index = ${index} , array = ${array}`);
});

函数体内的 argument ,用于函数接受任意多个参数

1
2
3
4
5
function foo(a,b,c){
if(arguments.length === 2){
c=0;
}
}

变量作用域

1
2
3
4
5
6
7
8
9
10
11
12
'use strict'
function foo(){
var x = 1;
function boo(){
var y = x+ 1000;
var x = 100 ;
console.info(`in boo x= ${x} , y = ${y}`); // y=NaN
}
boo();
console.info(`in foo x = ${x}`);
}
foo();

装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
"use strict"
//计算函数调用次数
var oldParseInt = window.parseInt;
var callCount = 0;
window.parseInt = function(){
callCount++;
return oldParseInt.apply(null,arguments);
};
console.info(callCount);
//test
console.info(parseInt(1.2));
console.info(parseInt(1.51));
console.info(parseInt(-1.8));
console.info(callCount);

高阶函数 Higher-order-functioin

1
2
3
4
5
'use strict'
function add(a,b,f){
return f(a) + f(b);
}
console.info(add(1,-1,Math.abs));

pow

1
2
3
4
5
6
7
'use strict'
function pow(x){
return x*x;
}
var arr = [1,2,3,4,5,6,7,8,9];
var arr1 = arr.map(String);
console.info(arr1);

reduce 含义: [x1,x2,x3,x4].reduce(f) = f(f(f(x1,x2),x3),x4)

1
2
3
4
5
6
//计算乘积
'use strict'
arr = [1,2,3,4];
arr.reduce(function(x,y){
return x*y;
});

不使用 window.parseInt() 转换字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
'use strict'
function string2int(s){
var ret = 0;
var arr = s.split('');
arr = arr.map(function(x){
return +x;
});
ret = arr.reduce(function(x,y){
return 10 * x + 1 * y ;
});
return ret;
}
// 测试:
if (string2int('0') === 0 && string2int('12345') === 12345 && string2int('12300') === 12300) {
if (string2int.toString().indexOf('parseInt') !== -1) {
console.info('请勿使用parseInt()!');
} else if (string2int.toString().indexOf('Number') !== -1) {
console.info('请勿使用Number()!');
} else {
console.info('测试通过!');
}
}
else {
console.info('测试失败!');
}

首字母大写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'use strict'
function normalize(arr){
return arr.map(function(name){
var letters = name.split('');
var first = letters.shift().toUpperCase();
letters = letters.join("");
letters = letters.toLowerCase();
letters = first + letters;
return letters;
});
}
// 测试:
if (normalize(['adam', 'LISA', 'barT']).toString() === ['Adam', 'Lisa', 'Bart'].toString()) {
alert('测试通过!');
}
else {
alert('测试失败!');
}

1
2
3
4
5
6
7
8
'use strict'
var arr = ['1','2','3'];
//var xoo = arr.map(parseInt); //[1,NaN,NaN]
var foo = arr.map(function(x){
return parseInt(x,10);
});
var boo = arr.map(Number);
console.info(foo);

filter

1
2
3
4
5
6
7
'use strict'
var arr = [1,2,3,4,5,6,7,8,9];
var r = arr.filter(function(el,idx,sel){
return el % 2 == 0 ? true : false;
});
console.info(arr);
console.info(r);

排序 去除重复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'use strict'
var r,arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
function distinct(){
var map = new Map();
var ret = [];
arr.forEach(function(el,idx,sel){
map.set(el,idx);
});
map.forEach(function(value,key,sel){
ret.push(key);
});
ret.sort();
return ret;
}
console.info(distinct());
1
2
3
4
5
6
7
8
9
// 使用 filter 去重复的答案
'use strict'
var r,arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
function distinct(){
return arr.filter(function(el,idx,sel){
return sel.indexOf(el) === idx ? true : false;
});
}
console.info(distinct());

过滤留下质数,除了1和自身以外,不能被整除 [2,3,5,7,11]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
'use strict'
function get_primes(arr) {
return arr.filter(function(el,idx,sel){
var ret = false;
if(el>1 && el <=3){
ret = true;
}else {
for(let i = 2 ; i <= Math.sqrt(el); i++){
ret = true;
if(el % i === 0){
ret = false;
break;
}
}
}
return ret;
});
}
var
x,
r,
arr = [];
for (x = 1; x < 100; x++) {
arr.push(x);
}
r = get_primes(arr);
if (r.toString() === [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97].toString()) {
console.info('测试通过!');
} else {
console.info('测试失败: ' + r.toString());
}

sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use strict'
var arr1 = ['Google', 'Apple', 'Microsoft'].sort();
//["Apple","Google","Microsoft"]
var arr2 = ['Google', 'apple', 'Microsoft'].sort();
//["Google", "Microsoft", "apple"]
var arr3 = [10,20,1,2].sort();
//[1,10,2,20]
arr3.sort(function(x,y){
return x < y ? -1 : 1;
});//[1,2,10,20]
arr2.sort(function(x,y){
x = x.toLowerCase();
y = y.toLowerCase();
return x < y ? -1 : 1;
});//['apple','Google','Microsoft']
console.info(arr3);

使用var的话,无法记录函数中i 那个时刻的状态值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'use strict'
var count = function(){
var arr = [];
for(let i=0;i<3;i++){
arr.push(function(){
return i * i;
});
}
return arr;
}
var fs = count();
console.info(fs[0]());
console.info(fs[1]());
console.info(fs[2]());

在返回的对象中,实现了一个闭包,该闭包携带了局部变量x,并且,从外部代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use strict'
var create_counter = function(start){
var times = start || 0;
function inc(){
return ++times;
}
return inc;
}
var counter1 = create_counter();
var counter2 = create_counter(100);
console.info("counter1 :" + counter1());
console.info("counter1 :" + counter1());
console.info("counter1 :" + counter1());
console.info("counter2 :" + counter2());
console.info("counter2 :" + counter2());
console.info("counter2 :" + counter2());

闭包就是携带了状态的函数,并且状态可以对外隐藏。

1
2
3
4
5
6
7
8
9
10
'use strict'
function create_pow(n){
return function(x){
return Math.pow(x,n);
}
}
var pow2 = create_pow(2);
var pow3 = create_pow(3);
pow2(5);//25
pow3(3);//27

阿隆佐·邱奇 只用函数实现现运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
'use strict'
var zero = function(f){
return function(x){
return x;
}
};
var one = function(f){
return function(x){
return f(x);
}
};
var add = function(a,b){
return function(f){
return function(x){
return a(f)(b(f)(x));
}
}
};
var two = add(one,one);
var three = add(two,one);
var four = add(two,two);
var five = add(four,one);
five(function(){
console.info("this is five");
})();
//下面是帮助理解用的
var x1 = zero(
function(){
console.info(0);
}
)();
console.info(`x1 = ${x1}`);
var two = function(f){
return function(x){
return f(f(x));
}
};
x1 = two(
function(x){
console.info(`two x = ${x}` );
}
)(123);