一,数据类型
五种原始类型:
number,
string, 对应的包装类String
boolean,
null,
undefined,
对象类型:
Function, Array, Date。。。
相等 vs 严格相等
typeof vs instanceof vs Object.prototype.toString
二,表达式
数组,对象初始化表达式:
[1,2] ==> new Array(1,2);
[1,,,4] ==> [1, undefined, undefined, 4];
{x:1, y:2} ==> var o = new Object(); o.x1 = 1; o.x2 = 2;
函数表达式:
var func = function(){};
// 直接将函数用括号扩起来,然后再最后面写一个括号,表示函数调用。
(function(){console.log('hhhhiiii');})();
属性访问表达式:
var o = {x:'hello'};
//访问1
o['x']
//访问2
o.x
对象创建表达式:
new Func(1,2); //带参数
new Object; //不带参数
调用表达式:
func(); //函数名加上()
三,运算符
三目运算符:c ? a: b
逗号运算符:var val = (1,2,3); // val == 3;
delete:删除一个属性
in:判断一个属性是否属于某个对象
instanceof:根据原型链来判断
new/this/typeof/void,略
四,对象
对象中包含一系列属性,属性是无序的,一个属性由key和value组成。
对象的创建:(1)字面量var o = {x:1, y:2},可嵌套 (2)new 构造器 (3)Object.create({x:3});
原型链(有点像Java里面类的继承)
五,属性标签
用下面的方法获取一个对象的属性值
Object.getOwnPropertyDescriptor({pro:true}, 'pro');
{ value: true,
writable: true,
enumerable: true,
configurable: true }
//如果属性不存在,则返回undefined
Object.getOwnPropertyDescriptor({pro:true}, 'prr');
undefined
给对象创建一个属性
> Object.defineProperty(person, 'name', {
... configurable:false,
... writable:false,
... enumerable:true,
... value:'Jackey'
... });
//因为writable是false的,所以不能修改name的属性
> person.name //打印当前name值
'Jackey'
> person.name=100; //修改name值
100
> person.name; //可以看到并没有被修改
'Jackey'
> delete person.name; //删除也是删除不了的
false
对象标签:proto, isExtensible, class
对象序列化
六,数组
6.1 弱类型,什么样类型的元素都可以往里面塞
var arr = [1, true, null, undefined, {k:1}, [1,2,3]];
6.2 创建数组
//除了使用6.1那样使用字面量的方法,还可以如下
var arr = new Array();
var arrWithLength = new Array(10);
var arrLikeLiteral = new Array(true, false, null, 11, 'rrr');
6.3 元素增删除
动态,无需指定大小.
var arr = [11,22,33,44];
//尾部添加元素
arr.push(-55);
//头部添加元素
arr.unshift(-11)
//尾部删除元素
arr.pop();
//头部删除元素
arr.shift();
6.4 数组迭代
//法1
for(var i = 0; i
}
//法2
for(i in arr) {
console.log(arr[i]);
}
//原型链上添加元素
Array.prototype.x='added';
//遍历数组会访问添加的元素
//使用这个判断可以过滤
if(arr.hasOwnProperty(i)){
console.log(arr[i]);
}
6.5 数组方法
Array.prototype.join
Array.prototype.reverse
Array.prototype.sort //1.in place 2.sort by string order
Array.prototype.concat //array to be filled will be flatted
Array.prototype.slice //原数组不被修改
Array.prototype.splice //原数组被修改
Array.prototype.forEach
Array.prototype.map //数组映射
Array.prototype.filter //数组过滤
Array.prototype.every //表示每一个元素都要符合一定的条件
Array.prototype.some //表示任一个元素,只要一个符合
Array.prototype.reduce
Array.prototype.reduceRight
Array.prototype.indexOf
Array.prototype.lastIndexOf
Array.isArray
示例 reduce
var arr = [11, 22, 33, 44];
var sum = arr.reduce(function(x, y){
return x+y;
}, 0);
var max = arr.reduce(function(x ,y){
return x>y?x:y;
});
示例 判断数组
Array.isArray({});
[] instanceof Array;
({}).toString.apply([]) === '[object Array]';
[].cOnstructor=== Array;
数组 vs 对象
相同
1.都可以继承
2.都可以当作对象添加/删除属性
不同
数组自动更新length
数组对象继承Array.prototype上的大量数组操作方法
七,函数
Js函数不同于其他语言中的函数,js函数可以像其他对象那样操作和传递,所以js函数也称为函数对象.
7.1 调用方法
直接调用: foo();
对象方法式调用: o.method();
构造器调用: new Foo();
call/apply/bind: func.call(o);
函数声明
function add(a, b) {
a = +a;
b = +b;
if(isNaN( || isNaN(b)) return;
return a + b;
}
函数表达式
//function variable
var add = function(a,b) {
// do sth
}
//Immediately Executed Function
(function() {
// do sth
})();
// first-class function
return function() {
// do sth
}
// Named function expression
var add = function foo(a,b) {
// do sth
}
变量&函数的声明前置
7.2 this
(1) 在浏览器中,全局的this,就是window;
在node.js中,全局的this,就是global.
console.log(this.document === document);
console.log(this === window);
this.a = 37;
console.log(window.a);
function f1() {
return this;
}
f1() === global; // true
严苛模式下:
function f1() {
"use strict";
return this;
}
f1() === global; //false
f1() === undefined; //true
(2) 作为对象方法的函数的this
var o = {
prop:37;
f:function() {
return this.prop;
}
};
console.log(o.f());
(3) 对象原型链上的this
var o = {f:function(){return this.a + this.b;}};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f());
(4) 构造器中的this
function MyClass() {
this.a = 73;
//没有return或返回值为基本类型,则将this作为返回值
}
var o = new MyClass();
console.log(o.a); //73
function C2() {
this.a = 37;
return {a:38}; //回值为对象类型,则将该对象作为返回值
}
o = new C2();
console.log(o.a); //38
(5) call/apply与this
function add(c, d) {
return this.a + this.b + c+ d;
}
var o = {a:1, b:3};
add.call(o, 5,7); //1+3+5+7 = 16
add.apply(o, [10, 20]); //1+3+10+20=34
function bar() {
console.log(Object.prototype.toString.call(this));
}
bar.call(7); //"[object Number]"
(6) bind与this
function f() {
return this.a;
}
var g = f.bind({a:"test"});
console.log(g());
var o = {a:37, f:f, g:g};
console.log(o.f(), o.g());
7.3 函数属性&arguments
function foo(x, y, z) {
arguments.length;
arguments[0];
arguments[0] = 10;
x;
arguments[2] = 100;
z;
arguments.callee === foo;
}
foo(1, 2);
foo.name; //函数名
foo.length; //形参个数
arguments.length; //实参个数
call & apply
function fo(x, y) {
console.log(x, y, this);
}
fo.call(100, 1,2); // 1,2,Number(100)
fo.apply(true, [3,4]); //3,4,Boolean(true)
fo.apply(null); //undefined, undefined, window
fo.apply(undefined); //undefined, undefined, window
bind, 改变函数里面的this
this.x = 9;
var module = {
x:81,
getX: function() {return this.x}
};
module.getX(); //81
var getX = module.getX;
getX(); // 9
var boundGetX = getX.bind(module);
boundGetX(); // 81
bind与currying
function add(a,b,c) {
return a+b+c;
}
var func1 = add.bind(undebined, 100); //100被赋值给第1个参数a
func1(1,2); //103, 1赋值给b,2赋值给c
var func2 = func1.bind(undebined, 200); //因a已经绑定到了a,200会绑定到b
func2(10); //310, 10绑定到c
bind与new
function foo() {
this.b = 100;
return this.a;
}
var func = foo.bind({a:1}); //this指向bind的参数
func(); //因为this指向对象{a:1},所以返回值this.a就是1
new func(); //会产生一个空对象,空对象指向foo_prototype,返回值忽略this.a;直接将100返回(what the fuck!)
八,函数和作用域
8.1 闭包
(1) 演示闭包
function outer() {
var localVal = 30;
return function() {
return localValue;
}
}
var func = outer(); //外部函数调用完之后,localVal不能立即释放,因为return的函数引用了它
func(); //30
(2) 闭包常用错误:循环闭包
function Outer {
var tempList = [];
for (var i = 0; i <10; i++) {
tempList[i] = function () {
return i;
}
}
return tempList;
}
//调用方:
var list = Outer();
for (var i = 0; i
}
(3)闭包概念
闭包(也称词法闭包或函数闭包)是指一个函数或函数的引用,与一个环境变量绑定在一起.这个引用环境是一个存储该函数每个非局部变量(也叫自由变量)的表.
闭包,不同于一般的函数,它允许一个函数在立即词法作用域外调用时,仍可访问非本地变量.
8.2 作用域
js没有块作用域的概念
(1) 全局,局部
var globle_a = 10; //全局变量
(function() {
var func_b = 20; //函数局部变量
})();
console.log(globle_a); //10
console.log(func_b); //error, b is not defined
for(var item in {a:1, b:2}) {
console.log(item);
}
console.log(item); // item is still in scope
eval("var a = 1;");
(2) 执行上下文
全局的this(浏览器)
一般函数的this(浏览器)
作为对象方法的函数的this
对象原型链上的this
get/set方法与this
构造器中的this
call/apply方法与this
bind方法与this
九,OOP
9.1 基于原型的继承
function Foo() {
this.y = 2;
}
typeof Foo.prototype; // "object"
Foo.prototype.x = 111;
var obj = new Foo();
obj.y; //2
obj.x; //111
Foo.prototype的结构:
{
constructor:Foo,
_proto_:Object.prototype,
x:1
}
prototype是函数上预设的对象属性,原型是构造器的prototype属性(what the fuck!!!)
9.2 图解原型链
对象继承代码示例
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.hi = function() {
console.log('Hi, my name is '+this.name +", I'm " + this.age + " years old now.");
};
Person.prototype.LEGS_NUM = 2;
Person.prototype.ARMS_NUM = 2;
Person.prototype.walk = function() {
console.log(this.name + " is walking");
};
function Student(name, age, className) {
Person.call(this, name, age);
this.className = className;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.cOnstructor= Student;
Student.prototype.hi = function() {
console.log('Hi, my name is ' + this.name + ", I'm " +
this.age + " years old now, and from " +
this.className + ".");
};
Student.prototype.learn = function(subject) {
console.log(this.name + ' is learning ' + subject + ' at '+ this.className+'.');
}
// test
var littleTom = new Student('Tom', 20, 'Class 3, Grade 2');
littleTom.hi();
littleTom.LEGS_NUM;
littleTom.walk();
little.learn('computer science');
多种方式实现继承
function Person() {}
function Student() {}
Student.prototype = new Person(); //1
Student.prototype = Object.create(Person.prototype); //2
Student.prototype.cOnstructor= Person; //3