js 语言精粹 (摘要)
1.0 js注释 2种
1.1 // 单行注释
1.2 /* */ 多行注释
2.0 标识符
标识符由一个字母开头,后面选择性的加上一个或多个字母,数字或下划线
标识符被用于语句,变量,参数,属性名,运算符和标记。
3.0 保留字
如 if else false true function 等这些 标识符是不能使用的,因为js规定不让用
原因是容易混淆程序。
4.0 数字
js 只有一种数字类型就是number所以:
4.1 1和1.0 是相等的
4.2 值NaN是一个数值,它不等于任何值,包括他自己,
判断一个值是不是NaN 用函数isNaN(number)来判断
只有当number的值是NaN的时候才返回true,否则全部返回false
4.3 字面量有指数的部分 比如100和1e2 是相等的
1e2 就是指数 计算方式是 e之前的部分乘以10的e之后部分的次方
==100
5.0 字符串
5.1字符串字面量被单引号或双引号包裹,
5.2 js都是用unicode表示的字符集
(Unicode统一码它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求)
5.3 \(反斜杠是转译字符)
6.0 下面的值会被当做假(false)
6.1 false
6.2 null
6.3 undefined
6.4 空字符串 ' '
6.5 数字 0
6.6 数字 NaN
对应的其他的情况全部是真(true)
7 for in 是用来枚举一个对象的
还有就是我们通过检测 object.hasOwnProperty()来确定这个属性名是该对象的还是从其原型链里找到的。
如:people = {
name:'1',
age:'2',
}
for(myvar in people){
if(obj.hasOwnProperty(myvar)){
......
}
}
8 typeof 运算符
8.1 typeof 运算符产生的值有 'number','string','boolean','undefined','object','function'
8.2 当typeof 数组或者null的时候值是 'object'
9 对象
9.1 js的简单的数据类型
string number boolean null undefined
其他的都是对象,对象是属性的容器,属性值可以是除undefined值之外的任何值。
10.0 对象字面量如:
var people = {};
var water = {'color':'red','weight':'18'}
11.0 检索 也就是获取对象里面的某个值
11.1 water.color (推荐这种)
11.2 water['color']
11.3 如果你检索一个并不存在的成员属性的值的时候返回undefined
water.height //undefined
用||可以给默认值
如: var a = water.height || '16'
意思就是a等于对象的height属性的值,如果值不存在就是16
12.0 引用
对象通过引用来传递,他们永远不会被复制
var x = y;
x.name = "san";
var a = y.name;
// x,y是指向同一个对象的引用,所以值为 san
var b = {},c={},d={};
// a,b,c,每个都引用一个不同的空对象
b=c=d={}
//都引用同一个空对象
13.0 原型
每个对象都连接一个原型对象,并且他可以从中继承属性,所有通过对象字面量创建的对象都会连接到Object.prototype,它是javascript中的标配对象。
原型连接只有在检索值的时候才被永达,如果我们城市去获取对象的某个属性值,但该对象没有此属性名,那么js会试着从原型对象中获取属性值,如果那个原型对象也没有改属性,那么再从它的原型中寻找,依次类推,直到该过程最后到达终点Object.prototype。如果想要的属性完全不存在于原型链中,那么结果就是undefined,这个过程称为委托
原型关系是一种动态的关系,如果我们添加一个新的属性到原型中,该属性会立即对所有基于该原型创建的对象可见。
14.0 hasOwnProperty方法
如果对象拥有独有的属性,它将返回true,
hasOwnProperty方法不会检查原型链。
a.hasOwnProperty('constructor') //false
15.0 删除
delete运算符可以删除对象的属性,从而暴露出原型的属性如:
delete people.name 则 people上一级的原型的name就取出来了
16.0 减少全局变量污染,
如只创建一个对象
var myapp = {};
myapp.flight = {}
myapp.stooge = {}
还有一种方法有效减少全局污染,闭包
17.0 函数对象
函数对象连接到Function.prototype(该原型对象本身连接到Object.prototype)
每个函数对象在创建时也随配有一个prototype属性,它的值是一个拥有constructor属性且值即为该函数的对象。
18.0 函数字面量
// 创建一个名为add的变量,并用来把两个数字相加的函数赋值给它。
var add = function(a,b){return a+b;}
用法add(1,2)
一个内部函数除了可以访问自己的参数和变量,同时它也能自由访问把它嵌套在其中的父函数的参数和变量。通过函数字面量创建的函数对象包含一个连到外部上下文的连接。这被称为闭包。
19.0 调用
调用一个函数会暂停当前函数的执行,传递控制权和参数给函数。除了声明时定义的形式参数,每个函数还接收两个附加的参数:this和arguments.
this 的值取决于调用的模式,
js中一共有4中调用模式:
1 方法调用模式
2 函数调用模式
3 构造器调用模式
4 apply调用模式
20.0 方法调用模式
当一个函数被保存在一个对象的一个属性时,我们称它为一个方法,在方法里面有提取属性的动作就是.点和【】下标表达式,那么它就是被当做一个方法来调用。
如:var people = {
value:0,
add:function(a){
this.value += typeof a==="number" ? a : 1;
}
}
people.add() // peolple.value==1
people.add(2) // peolple.value==3
通过this可取得它们所属对象的上下文的方法称为公共方法。
21.0 函数调用模式
当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用的。
this不能共享该方法对对象的访问权。
解决方案:通过那个变量访问到this,
按照约定,我们把那个变量命名为that;
如:
people.double = function (){
var that = this;
var helper() = function(){
that.value = add(that.value,that.value);
}
helper();
}
people.double(); //6
22.0 构造器调用模式
在一个函数前面加上new来调用,那么背地里将会创建一个连接到该函数的prototype成员的县对象,同时this会被绑定到那个新对象上。
var Quo = function (str){
this.status = str;
}
Quo.prototype.get_status = function(){
return this.status;
}
var mu = new Quo('hello') // hello
一个函数,如果创建的目的就是希望结合new前缀来调用,那它就被称为构造器函数,按照约定,它们保存在以大写格式命名的变量里。
(不推荐使用)
23.0 apply调用模式
23.1 apply方法让我们构建一个参数数组传递给带哦用函数,它允许我们选择this的值,apply方法接收两个参数,第1个是要绑定给this的值,第二个就是一个参数数组。
24.0 this指向问题
函数内部的this指针指向的是函数的调用者。
25.0 参数 arguments
var sum =function(){
console.log(arguments[0])//1
console.log(typeof arguments)//object
}
sum(1,2,3)
函数被调用时,会得到一个“免费”的参数,那就是arguments数组,可以通过他来访问传递给他的参数列表,这样就可以编写一个无需指定参数个数的函数。但是arguments并不是一个真正的数组,是个类似数组的对象,并且没有数组的方法。
26.0 异常exception
异常会干扰程序的正常流程
throw语句中断函数的执行,抛出一个exception对象
throw{
name:'1',
msg:'yichang'
}
一个try语句指回有一个捕获所有异常的catch代码块
try{
}catch(e){
}
27.0 扩展类型
给对所有函数增加方法
Function.prototype.method =function(name,func){
this.prototype[name] = func;
return this;
}
通过给Function.prototype增加一个method方法,我们下次给对象增加方法的时候就不必键入prototype这几个字符,省掉了一点麻烦。
// 取整数
Number.method('int',function(){
return Math[this<0 ?'ceil':'floor'](this);
})
console.log((-10/3).int());// -3
// 移除字符串收尾空白的方法
String.method('trim',function(){
return this.replace(/^\s+|\s+$/g,'');
})
console.log(' ok '.trim());// ok
28.0 递归(recursion)
递归函数就是会直接或间接的调用自身的函数。
尾递归:是一种在函数的最后执行递归调用语句的特殊形式的递归。这意味着如果一个函数返回自身递归调用的结果,那么调用的过程会被替换为一个循环,他可以显著提高速度。
如:
var fac = function fac(i,a){
a = a || 1;
if(i<2){
return a;
}
return fac(i-1,a*i)
}
fac(4)//24
29.0 作用域(scope)
作用域控制着变量与参数的可见性和生命周期。
30.0 闭包(closure)
函数可以访问它被创建时所处的上下文环境。
31.0 回调(callbacks)
函数使得对不连续事件的处理变得更容易,
如:js是异步的,就是之间没有联系,但是结果是我们必须让它有联系,怎么办呢?回调
32.0 模块
模块模式的一般形式是:一个定义了私有变量和函数的函数,利用闭包创建可以访问私有变量和函数的特权函数,最后返回这个特权函数,或者把他们保存到一个可访问到的地方。
// 构造一个产生序列号的对象
var maker =function(){
var prefix ='';
var seq =0;
return {
set_prefix:function(p){
prefix = String(p);
},
set_seq:function(s){
seq = s;
},
gensym:function(){
var result = prefix+seq;
seq +=1;
return result;
}
};
}
var seqer =maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
var unique = seqer.gensym();
console.log(unique);// Q1000
33.0 柯里化
科里化也叫‘局部套用’,是把多参数函数转换为一系列单参数函数并进行调用的技术。
34.0 fibonacci数列,中文名叫 裴波那契数列,他的特点是,掐年响铃两项之和等于后面一项的值。
// 构造一个产生序列号的对象
var fib =function(n){
return n<2?n:fib(n-1)+fib(n+2);
}
for(var i=0;i<=10;i++){
console.log(i+'--'+fib(i))
}
// fib被调用了453次,我们调用了11次,它自身调用了442次去计算,这计算量太大
// 用记忆的办法
var fi =function(){
var memo = [0,1];
var fb =function(n){
var res = memo[n];
if(typeof res !=='number'){
res =fb(n-1)+fb(n-2);
memo[n] = res;
}
return res;
}
return fb;
}()
let a =fi(3)
console.log(a)// 3
我们把这项技术推广一下,
var memoizer =function(memo,formula){
var recur =function(n){
var result = memo[n];
if(typeof result !=='number'){
result = formula(recur,n);
memo[n] =result;
}
return result;
};
return recur;
}
var fibonacci =memoizer([0,1],function(recur,n){
return recur(n-1)+recur(n-2);
})
console.log(fibonacci(4))//3
// 实现阶乘的函数
var fac =memoizer([1,1],function(recur,n){
return n*recur(n-1);
})
console.log(fac(3))//6
35.0 继承
在基于类的语言中,对象是类的实例,并且类可以从另外一个类继承,js是一门基于原型的语言,这意味着对象直接从其他对象继承。
36.0 创建一个使用原对象作为其原型的新对象beget(孕育)
(推荐写法)
if(typeof Object.beget !== "function"){
Object.create = function(o){
var f = function(){};
F.prototype = o;
return new F();
}
}
var cat = {
name:'',
age:'12'
}
var myCat = Object.create('mimi');
37.0 js实现私有属性(重点)
js不是面向对象的语言
37.1 基于编码规范约定的实现
我们约定以下划线_开头的变量约定为私有成员
function Person(name){
this._name = name;
}
这只是约束,很容易打破的,而且并没有实现私有属性。
37.2 基于闭包的实现
构造函数内部定义局部变量和特权函数,其实只能通过特权函数访问此变量。如
function Person(name){
this._name = name;
this.getName = function(){
return _name;
}
}
var person = new Persoan('ll')
这种方法实现了私有属性的隐藏,只能通过特权函数getName来获得
alert(person._name)//undefined
alert(persoan.getName())//'ll'
很多开发者都采用这种模式,但缺陷:
私有变量和特权函数只能在构造函数中创建,通常来讲,构造函数的功能只能负责创建县对象,方法应该共享在prototype上,特权函数本质上是存在于每个实例中的,而不是prototype上,增加了资源占用。
37.3 基于强引用散列表的实现方式
js不支持Map数据结构,所谓强引用散列表方式其实是Map模式的一种变体,简单来讲,就是给每个实例新增一个唯一的标识符,以此标识符为key,对应的value便是这个实例的私有顺序ing,这时key-value保存在一个Object内,如:
var Person = (function() {
var privateData = {},
privateId = 0;
function Person(name) {
Object.defineProperty(this, "_id", { value: privateId++ });
privateData[this._id] = {
name: name
};
}
Person.prototype.getName = function() {
return privateData[this._id].name;
};
return Person;
}());
上述代码的有以下几个特征:
使用自执行函数创建Person类,变量privateData和privateId被所有实例共享;
privateData用来储存每个实例的私有属性name的key-value,privateId用来分配每个实例的唯一标识符_id;
方法getName存在于prototype上,被所有实例共享。
这种方式在目前ES5环境下,基本是最佳方案了。但是仍然有一个致命的缺陷:散列表privateData对每个实例都是强引用,导致实例不能被垃圾回收处理。如果存在大量实例必然会导致memory leak。
造成以上问题的本质是JavaScript的闭包引用,以及只能使用字符串类型最为散列表的key值。针对这两个问题,ES6新增的WeakMap可以良好的解决。
37.4 基于weakMap的实现方式
WeakMap有以下特点:
支持使用对象类型作为key值;
弱引用。
根据WeakMap的特点,便不必为每个实例都创建一个唯一标识符,因为实例本身便可以作为WeakMap的key。改进后的代码如下:
var Person = (function() {
var privateData = new WeakMap();
function Person(name) {
privateData.set(this, { name: name });
}
Person.prototype.getName = function() {
return privateData.get(this).name;
};
return Person;
}());
改进的代码不仅仅干净了很多,而且WeakMap是一种弱引用散列表, 这意味着,如果没有其他引用和该键引用同一个对象,这个对象将会被当作垃圾回收掉。解决了内存泄露的问题。
38.0 数组字面量
一个数组字面量是在一对方括号中包围0个或多个用逗号分隔的值的表达式,,数组的第一个值将获得属性名‘0’,第二个是‘1’;
var empty = [];
var numbers = ['zero','one']
js 允许数组包含任意混合类型的值。
39 长度(length)
39.1如果数组长度是5,然后给这个
array.length = 3,这也可以起到截取数组的作用
39.2 通过下标指定,如添加到尾部
array[array.length] = '1'
39.3 push 方法
arr.push('go')
39.4 delete (删除)
delete array[2]
把数组第三个位置删除掉了,这个位置就变成了undefined
39.5 splice方法
第一个参数是数组中的序列号,第二个参数是要删除的元素的个数如:
var a = [1,2,3,4,5,6]
var b = a.splice(2,0)// []
var b = a.splice(2,1)
b//[3]
a// [1, 2, 4, 5, 6]
39.6 枚举(enumeration)
js数组是对象,所以可以用for in 但是不能保证属性的顺序,所以,用for(i=0;i<length;i++)的方式
39.7 js数组和对象使用的时候很容易混淆,
使用规则,当属姓名是小而连续的整数时,你应该使用数组,否则使用对象。
typeof array == 'object'
js没有一个很好的机制区分一个对象是否为数组,
es5 :例如
var is_array = function(value){
return Object.prototype.toString.apply(value) === '[object Array]';
}
es6: Array.isArray([]);// => true
40.0 方法
给Array.prototype扩充一个函数,每个数组都继承了
这个方法,我们定义了一个reduce方法,他接受一个函数和一个初始值作为参数,会计算出一个新值。
Array.method('reduce',function(f,value){
var i ;
for(i=0;i<this.length;i++){
value = f(this[i],value);
}
return value;
})
// 创建一个数组
var data = [4,8,15,16,23,42];
var add = function (a,b){
return a+b;
}
var mult = function(a,b){
return a*b;
}
// 调用data的reduce方法,传入add函数
var sum = data.reduce(add,0);// 108
var product =data.reduce(mult,1) //7418880
因为数组其实就是独享,所以我们可以直接给一个单独的数组添加方法
// 给data数组添加一个total方法
data.total = function(){
return this.reduce(add,0)
}
total = data.total()//108
因为字符串‘total’不是整数,所以给数组添加一个total属性不会改变它的length
41.0 给数组指定初始值,
你用【】的得到一个新数组,它将是空,如果你访问一个不存在的元素,得到的值是undefined,我们来构建一个数组并且给这个数组都设置初始值
Array.dim = function (dimension,initial){
var a = [],i;
for(i=0;i<dimension;i+=1){
a[i] = initial;
}
return a;
}
// 创建一个包含10个0的数组
var myArray = Array.dim(10,0)
js 没有多维数组,如果要实现多维数组,你必须自己去创建那个第二维的数组;
for(i=0;i<n;i+=1){
my_array[i] = [];
}
一个空的矩阵的每个单元会拥有一个初始值undefined,如果你希望他们有不同的初始值,你必须明确的设置他们。
Array.matrix = function(m,n,initial){
var a,i,j,mat = [];
for(i=0;i<m;i++){
a = [];
for(j=0;j<n;j++){
a[j] = initial;
}
mat[i] = a
}
reurn mat
};
// 构造一个用0填充的4*4矩阵
var myMatrix = Array.matrix(4,4,0)
myMatrix[3][3]//0
// 用来构造一个单位矩阵的方法
Array.indentity = function (n){
var i,mat = Array.matrix(n,n,0);
for(i=0;i<n;i++){
mat[i][i] = 1;
}
return mat
}
myMatrix = Array.indentity(4)
myMatrix[3][3]//1
42.0 正则表达式
它应用在一些方法中,对字符串中的信息实现查找,替换和提取的操作。
可处理正则表达式的方法有
regexp.exec
regexp.test
string.match
string.replace
string.search
string.splite
43.0 方法
array.contact(item...)
let a = [1,2]
let b = [2,3]
let c = a.contact(b) //[1,2,2,3]
44.0 array.join()
先把数组构造成字符串,然后再分割
let a = [1,2,3]
let b = a.join('')//123
45.0 array.pop()
移除数组中的最后一位
let a = [1,2,3]
let b
b=a.pop()
3
a// [1, 2]
b=a.pop()
2
b=a.pop()
1
a//[]
b=a.pop()//undefined
改变原来的数组并返回长度,,如果当a是empty的时候,返回的就是undefined
46.0 array.push()
在末尾添加元素,并返回长度,同上
47.0 array.reverse()
let a = [1,2,3]
let b = a.reverse();//[3,2,1]
48.0 array.shit()
let a = [1,2,3]
let b = a.shift();//a[2,3] b//1
如果a是空,则b返回undefined
shift 移除数组中的第一个元素,并返回这个元素
49.0 array.slice(start,end)
从array[start]开始,到array[end]结束,不包括end
并且end是可选参数
a = [1,2,3]
let e = a.slice(1,2) //[2]
let b = a.slice(0,1)//[1]
let c = a.slice(1)//[2,3]
50.0 array.sort()
对数组排序,从小到大,,
但是会先转化为字符串,再排序
let a = [4,2,15,26,41]
a.sort()//[15,2,26,4,41]
真正的比较大小的
a.sort(function(a,b){
return a-b;
})
但是如果里面有字符串就不行了,比如
m = ['a','c','aa',4,3,8,2]
m.sort(function(a,b){
if(a===b){
return 0;
}
if(typeof a === typeof b){
return a<b ? -1:1;
}
return typeof a< typeof b ? -1:1;
})
// [2,3,4,8,'a','aa','c']
51.0 array.splice(start,deleteCount,item...)
start开始位置,删除的个数,替换的元素
如:
let a = [1,2,3]
let b = a.splice(1,1)
a//[1,3]
b//[1]
d = a.splice(0,3,'2','4')
d// [1, 3]
a// ["2", "4"]
52.0 array.unshift(item...)
插入到数组的开始位置,不限制个数,并返回新数组的长度
let a = [1,2]
b=a.unshift('a','b')
// a ['a','b',1,2]
// b 4
53.0 function.apply(thisArg,argArray)
apply方法调用function,传递一个会被绑定到this上的对象和一个可选的数组作为参数
如:
Function.method('bind',function(that){
var method = this,
slice = Array.prototype.slice,
args = slice.apply(arguments,[1]);
return function(){
return method.apply(that,args.contact(slice.apply(arguments,[0])))
};
});
let a = function(){
return this.value;
}.bind({value:666});
alert(x());//666
54.0 Number
number.toExponential(fd)
把number转换成一个指数形式的字符串,参数是控制小数点的位数(0~20),不填的话就是0
55.0 number.toFixed(fd)
把number换成一个十进制的字符串,也是0~20
Math.PI.toFixed(0)// 3
Math.PI.toFixed()// 3
Math.PI.toFixed(2)// 3.14
56.0 number.toPrecision(precision)
也是把number转换成十进制字符串,可可宣参数是控制数字的精度,在0~21之间,会四舍五入的 并且我测的不在比21大也行啊!
Math.PI.toPrecision(21)
"3.14159265358979311600"
Math.PI.toPrecision(3)
"3.14"
Math.PI.toPrecision(50)
"3.1415926535897931159979634685441851615905761718750"
57.0 number.toString(radix)
把number转换为一个字符串,可选参数radix控制基数,值必须在2~36,默认是以10为基数的,
Math.PI.toString(2) // 转换为2进制的
Math.PI.toString() // 转换为10进制的 3.141592653589793
58.0 object.hasOwnProperty(name)
这个obj包含一个名为name的属性,那么hasOwnProperty方法返回true,原型链中的同名属性是不会被检查的
let a = {member:true};
let b = Object.create(a)
let c = a.hasOwnProperty('member);// true
let d = b.hasOwnproperty('member' )//false
let e = b.member;// true
58.0 regexp.exec(string)
exec方法是正则表达式的最强大(最慢)的方法,如果成功匹配就会返回一个数组,数组下标为0的元素将包含正则表达式regexp匹配的子字符串,下标为1的元素是分组1捕获的文本,下标为2的元素是分组2捕获的文本,以此类推,如果匹配失败,它会返回null
59.0 regexp.test(string)
test方法最简单(最快),如果匹配到返回true,否则返回false。
60.0 String
60.1
// charAt 返回所在位置的字符串
let name ="1234";
console.log(name.charAt(1))//2
console.log(name.charAt(-1))//空字符串
console.log(name.charAt(8))//空字符串
60.2
// charCodeAt字符码
console.log(name.charCodeAt(0));//49
console.log(name.charCodeAt(1));//50
console.log(name.charCodeAt(2));//51
60.3
string.concat() 拼接字符串,很少用到,都用+
let s = 'C'.concat('a','t')// cat
61.0
61.1string.indexOf(searchString,position)
查找字符串出现的位置,如果没有出现,就返回-1,
如果后面跟位置的话,就是说,从这位置开始查起
let test = "qwertw";
let qq = test.indexOf('q') //0
let p = test.indexOf('w') //1
p = test.indexOf('w',2) //5
61.2 string.lastIndexOf(searchString,position)
同上,只不过是从最后一个位置开始
62.3 string.localeCompare(that)
比较两个字符串,如果小就为负数,相等就是0
let m = ['AAA','A','aa','a','Aa','aaa'];
m.sort(function(a,b){
return a.localeCompare(b)
})
["a", "A", "aa", "Aa", "aaa", "AAA"]
62.4 string.match(regexp)
match方法让字符串和一个正则表达式匹配,他根据g标识俩决定如何匹配,如果没有g,则string.match() 结果和regexp.exec(string)的结果相同。如果有,则返回一个数组。
62.5 string.replace(searchValue,replacevalue)
对string进行替换,searchValue 可以是一个字符串,或者一个正则对象,如果是一个字符串的时候,只能替换第一次出现的地方,
如果是一个正则表达式的话,并带有g标识,他就会替换所有里面的东西,没带g的话,也是只替换第一个
replaceValue 可以是一个字符串,也可以是一个函数,如果是一个字符串的时候,$拥有特别的含义
let old = /\((\d{3})\)/g
let ee = '(555)666-1212'.replace(old,'$1-') //"555-666-1212"
$特殊符号,请看
序列号 替换对象
$$ $
$& 整个匹配的文本
$number 分组捕获的文本
$` 匹配之前的文本
$' 匹配之后的文本
62.6 string.search(regexp) search方法和indexOf类似
他只接受一个正则表达式,匹配到返回第一个匹配的首字符的位置,没有匹配到返回-1 ,忽略g,没有第二个参数
let text = 'www qqq "12 ';
let ww = text.search(/["']/); // 8 位置是从0开始的
62.7 string.slice(start,end)
注意:string.substring()跟他的用法一样,只是不能处理负数
所以没有理由使用它
例子:
62.762.8 string.split(separator,limit)
以一定的形式分割成数组,limit是限制数组的个数的,
第一个参数可以是一个字符串,也可以是一个正则表达式。
demo:
var a ="0123456";
var b = a.split('',5);//['0','1','2','3','4']
let c ='192.168.156';
let d = c.split('.')//['192','168','156']
let q ='a|b|c';
let qq = q.split('|')//['a','b','c']
let ww = q.split(/\|/);//['a','b','c']
62.9
string.toLowerCase(), 把大写的字母转变为小写的字母
string.toUpperCase() 把小写字母转为大写字母
String.formCahrCode(); 根据一串数字返回一个字符串
let kit = String.fromCharCode(67,97,116)
// Cat;
63.0 函数是顶级对象
64.0 js 3种定义全局对象的方式
在函数外 var a =value;
直接给全局对象添加一个属性,在web浏览器中,全局对象是window
window.a = value;
不声明直接用 foo = value
65.0 typeof
typeof 68.3 // number
typeof null // object
所以判断 是否为null 可以这样 value === null
此外typeof 不能辨别null和对象,可以用判断语句
if(value && typeof value === 'object'){
value // 是一个对象或者数组
}
typeof 正则的话,各个浏览器就不太一样了,有的返回 ‘object’ 有的返回 function
66.0 parsetInt 把字符串转为整形,遇到非数字时会停止解析
当第一个字符串是0的时候,会基于8进制而不是十进制来求值
parseInt('08'),
所以这个parseInt 接收第二个参数,用作基数
parsetIng('08',10) //8 基于10进制的解析
67.0 浮点数相加是会有误差的,
0.1+0.2
68.0 NaN 一个特殊的数量值
typeof NaN === 'number' // true
NaN === NaN // false
NaN !== NaN // true
js提供了一个isNaN函数,可以辨别数字和NaN
isNaN(NaN) //true
isNaN('0') //false
isNaN('oop') //true
isNaN(0) //false
Infinity 属性用于存放表示正无穷大的数值。前面加一个负号-
就表示负无穷大
所以判断一个值,是否可用作数字的最佳方法是,使用isFinite函数
var isNumber = function isNumber(value){
return typeof value === 'number' && isFinite(value);
}
69.0 typeof 运算符不能辨别数组和对象,需要检测它的constructor 属性
if(value && typeof value === 'object' && value.constructor ===Array){
// value 是一个数组
}
但是在不同帧或窗口创建的数组将会给出false,所以下面的检测更可靠
if(Object.prototype.toString.apply(value) === '[object Array]'){
// value 是一个数组
}
还有arguments 数组不是一个数组,它只是一个有着length成员属性的对象,上面的检测会分辨出来arguments并不是一个数组。
70.0 如果要创建一个新对象,使用new操作符,
我们约定 这样的函数要用大写开头的形式命名,约定。
71.1 function 语句和function 表达式
他们很类似的
一个function语句就是其值为一个函数的var语句的速记形式。
function foo(){}
var foo = function foo(){}这种明确表明foo是一个包含一个函数值的变量。 要用好这门语言,理解函数就是数值很重要