JavaScript基础(上)数据类型、表达式和运算符、语句、对
2018-08-15 本文已影响6人
左左4143
数据类型
课程大纲
- 数据类型
- 表达式和运算符
- 语句
- 对象
- 数组
- 函数
- this
- 闭包和作用域
- OOP
- 正则与匹配模式
数据类型
-
原始类型
- number
- string
- boolean
- null
- undefined
-
对象类型
- Function、Array、Date……
隐式转换
//巧用加减号
var x = "37" - 7;
console.log(x);//输出30
var y = "37" + 7;
console.log(y);//输出377
//等于与严格等于
console.log("1.23"==1.23);//true;
var a = 1;
var b = "1";
console.log(a==b);//true;
console.log(a===b);//fales,会先判断类型;
var str = "string";
console.log(str.length);//输出 6
str.t = 3;
console.log(str.t);//输出undefined
//访问基础类型变量的属性时会将基础类型临时变换为对象类型 完成访问后临时对象会被销毁 所以str.t是没有值得
//类型检测
//typeof 适合基本类型及function检测 遇到null失效
console.log(typeof(100));//输出number
console.log(typeof("string"));//输出strin
//instanceof 适合自定义对象 也可以用来检测原生对象 在不同iframe和window间检测时失效
var b1 = [1,2] instanceof Array === true;
console.log(b1);//true
var b2 = new Object() instanceof Array === true;
console.log(b2);//false
//Object.prototype 通过{}.toString 拿到 适合内置对象和基本类型 遇到null 和undefined时失效(IE 6 7 8 返回[object Object])
console.log(Object.prototype.toString.apply([]));//输出 [object Array]
console.log(Object.prototype.toString.apply(function(){}));//输出[object Function]
表达式和运算符
//原始表达式 常亮、直接量、关键字、变量
3.14; "test"; null; this; true; i; j; k;
//复合表达式
10*20;
//数组,对象初始化表达式
[1,2]; new Array(1,2);//等价
[1,,,4]; [1,undefined,undefined,4];//等价
var a = {x:1,y:2}; var b = new Object(); b.x = 1; b.y = 2;//等价
//函数表达式
var fe = function(){};
(function(){console.log("hello world");}());
//属性访问表达式
var o = {x:1};
o.x;
o['x'];
//调用表达式
func();
//对象创建表达式
new Func(1,2);
new Object;
//运算符
//三元运算符
var val = 1>2?"NO":"YES";
//逗号运算符
var val2 = (1,2,3);//val = 3;
//delete 运算符
var obj = {x:1};
console.log(obj.x);//1
delete obj.x;
console.log(obj.x);//undefined
语句
//块 block
{
var str = "hi";
console.log(str);
}
// {a:1,b:2}//SyntaxError:Unexpected token:
var o = {a:1,b:2}//ok
//注意 没有块级作用域 下边这两种代码是一个效果
for (var i = 0; i < 3; i++){
var str = "hi1";
console.log(str);
}
console.log(i);//输出3
var j = 0
for(;j < 3; j++){
var str = "hi2";
console.log(str);
}
console.log(j);//输出3
//函数作用域
function foo(){
var a = 1;
console.log(a);//1
}
foo();
console.log(typeof a);//undefined
// var
function foo2() {
var a = b = 1;//这种写法 a 成为局部变量外部不能访问 b成为全局变量
}
foo2();
console.log(typeof a);//undefined
console.log(typeof b);//number
//声明多个变量的正确写法
var a = 1, b = 1;
//try catch语句
/*
try{
throw new Error("oops");
}catch(ex) {
console.log(ex);
}
try{
throw new Error("oops2");
} finally {
console.log("finally");
}
try{
throw "test";
} catch(ex) {
console.log(ex);
} finally {
console.log('finally2');
}
*/
//function 语句
//函数声明 函数语句
var f = fd();
console.log(f);//true
function fd(){
//do sth
return true;
}
//fe();//TypeError 异常
//函数表达式
var fe = function(){
//do sth
};
//在函数声明前调用函数可以成功 但是函数表达式前调用不可以
//for...in 遍历的顺序不确定
var p;
var obj = {x:1,y:2,z:3};
for (p in obj) {
console.log(typeof p +"\n"+ p);
}
//with 语句 可以修改作用域 现在已经不建议使用
with({x:1}){
console.log(x);
}
/* 浏览器中
with(document.forms[0]){
console.log(name.value);
}
*/
//严格模式
/**
* 严格模式是一种特殊的执行模式,它修复了部分语言上的不足,提供更强的错误检查,并增强安全性
*/
'use strict';//放在方法内部或者js文件开头
//严格模式不允许使用with 会报错
对象
- 对象的结构
- 创建对象
- 属性操作
- getter setter
- 属性标签
- 对象标签
- 序列化
- 对象方法
//创建对象
var obj1 = {x:1,y:2};
//嵌套
var obj2 = {
x:1,
y:2,
o:{
z:3,
n:4
}
}
//原型链
function foo(){};
foo.prototype.z = 3;
var obj = new foo();
obj.x = 2;
obj.y = 1;
obj.z//3;
typeof obj.toString;//'function'
'z' in obj;//true
obj.hasOwnProperty('z');//false
//访问对象中不存在的属性会在原型链上向上查找, 但赋值对象中不存在的属性时只会在对象上生成一个新属性
obj.z = 5;
obj.hasOwnProperty('z');//true
foo.prototype.z//仍然是3
obj.z;//5
// delete 只能删除对象本身的属性不能删除原型链上的属性
var obj3 = Object.create({x:1});
obj.x;//1
typeof obj3.toString//'function'
obj3.hasOwnProperty('x');//false
var obj4 = Object.create(null);
obj4.toString;//undefined
//对象的属性操作
var obj5 = {x:1,y:2};
obj5.x;//1
obj5["y"];//2
obj5["x"] = 3;
obj5.y = 4;
obj5.z;//undefined
//异常
var obj6 = {x:1};
obj6.y;//undefined
var yz = obj.y.z;//TypeError
obj.y.z = 2;//TypeError
var yz;
if(obj6.y){
yz = obj.y.z;
}
//或者
var yz = obj6 && obj6.y && obj6.y.z;
//属性删除
var person = {age:8,title:"fe"};
delete person.age;//true
delete person["title"];//true
person.age;//undefined
delete person.age;//true//虽然已删除 但现在对象中已经没有这个属性,所以返回true
delete Object.prototype;//false
var descriptor = Object.getOwnPropertyDescriptor(Object,'prototype');
descriptor.configurable;//false
var globalVal = 1;
delete globalVal;//false
(function(){
var localVal = 1;
return delete localVal;
}());//false
function fd(){
delete fd;//false
}
(function(){
function fd(){
return delete fd;
}
}());//false
//属性检测
var cat = new Object;
cat.legs = 4;
cat.name = "Kitty";
"legs" in cat;//true
"abc" in cat;//false
"toString" in cat;//true
cat.hasOwnProperty("legs");//true
cat.hasOwnProperty("abc");//false
cat.hasOwnProperty("toString");//false 对象上没有 原型链上才会有
cat.propertyIsEnumerable("legs");//true 属性是否可枚举
cat.propertyIsEnumerable("toString");//false
Object.defineProperty(cat,"price",{enumerable:false,value:1000});//生成一个不可枚举的属性
console.log(cat.propertyIsEnumerable("price"));//false
console.log(cat.hasOwnProperty("price"));//true
//属性赋值判断
if(cat && cat.legs){
cat.legs *= 2;
}
if(cat.legs != undefined) {
// 相当于 !==undefined or !== null 因为不是严格模式 undefinded 相当于null
}
if(cat.legs !== undefined) {
//严格模式 只判断undefined
}
//属性枚举
var o = {x:1,y:2,z:3};
"toString" in o;//true
o.propertyIsEnumerable('toString');//fals
var key;
for(key in o){
console.log(key);//x,y,z
}
var obj = Object.create(o);
obj.a = 4;
var key1;
for(key1 in obj){
console.log(key1);//a x y z
}
console.log("\n\n");
// 过滤原型链上的属性
var obj2 = Object.create(o);
obj2.a = 5;
var key2;
for(key2 in obj2){
if(obj2.hasOwnProperty(key2)){
console.log(key);
}
}
//set/get方法
var man = {
name:'Bosn',
weibo:'@Bosn',
get age(){
return new Date().getFullYear()-1988;
},
set age (val){
console.log('Age can\'t be to ' + val);
}
};
console.log(man.age);//30
man.age = 100;//Age can't be set to 100
console.log(man.age);//still 30
var woman = {
weibo:'@Bosn',
$age:null,
get age(){
if(this.$age == undefined) {
return new Date().getFullYear() - 1988;
} else {
return this.$age;
}
},
set age(val){
val = +val;
if(!isNaN(val)&&val > 0 && val < 150) {
this.$age = +val;
} else {
throw new Error('Incorrect val ='+val);
}
}
};
console.log(woman.age);//30
woman.age = 100;
console.log(woman.age);//100
//woman.age = 'abc';//Error: Incorrect val =NaN
//get/set 与原型链
function foo(){};
Object.defineProperty(foo.prototype,'z',{get:function(){return 1;}});
var obj = new foo();
console.log(obj.z);//1
obj.z = 10;
console.log(obj.z);//仍然是1
Object.defineProperty(obj,'z',{value:100,configurable:true});//configurable 是否可以delete,update属性
console.log(obj.z);//100
delete obj.z;
console.log(obj.z);//变回1
var o ={};
Object.defineProperty(o,'x',{value:1});//writable=false 不可写,configurable=false
var obj = Object.create(o);
console.log(obj.x);//1
obj.x = 100;
console.log(obj.x);//仍然是1 因为属性在原型链上并且不可写
Object.defineProperty(obj,'x',{writable:true,configurable:true,value:100});
console.log(obj.x);//100
obj.x = 200;
console.log(obj.x);//200
/**
* writable : 是否可写/可修改
* enumerable:属性是否可以被遍历,枚举,决定这个属性是否会在forin中出现
* configurable:属性是否可以再次被修改,是否可以通过delete删除属性
*/
//属性标签
console.log(Object.getOwnPropertyDescriptor({pro:true},'pro'));
//打印结果
/**
{ value: true,
writable: true,
enumerable: true,
configurable: true }
*/
console.log(Object.getOwnPropertyDescriptor({pro:true},'a'));//undefined
//----------
var pserson = {};
Object.defineProperty(pserson,'name',{
configurable:false,
writable:false,
enumerable:true,
value:'Bosn Ma'
});
//Object.defineProperty 接收三个参数 1、被设置属性的对象 2、属性的名字 3、属性标签对象
console.log(pserson.name);//Bosn Ma
person.name = 1;
console.log(pserson.name);//still Bosn Ma 因为writable 为false
delete pserson.name;//false 因为configurable 为false
//----------
Object.defineProperty(person,'type',{
configurable:true,
writable:true,
enumerable:false,
value:"Object"
});
console.log(Object.keys(pserson));//打印出['name'],而type没有打印出来 因为enumerable为false
//定义多个属性
Object.defineProperties(person,{
title:{
value:"fe",
enumerable:true
},
corp:{
value:"BABA",
enumerable:true
},
salary:{
value:50000,
enumerable:true,
writable:true
}
});//不写的属性标签默认为false 或者null
console.log(Object.getOwnPropertyDescriptor(person,'salary'));//{ value: 50000,writable: true,enumerable: true,configurable: false }
console.log(Object.getOwnPropertyDescriptor(person,'corp'));//{ value: 'BABA',writable: false,enumerable: true,configurable: false }
Object.defineProperties(person,{
title:{value:'fe',enumerable:true},
corp:{value:'BABA',enumerable:true},
salary:{value:10000,enumerable:true},
luck:{
get:function(){
return Math.random()>0.5?'good':'bad';
}
},
promote:{
set:function(level){
this.salary *= 1 + level * 0.3;
}
}
});
console.log(Object.getOwnPropertyDescriptor(pserson,'salary'));//{ value: 5000,writable: false,enumerable: true,configurable: false }
console.log(Object.getOwnPropertyDescriptor(pserson,'corp'));//{ value: 'BABA',writable: false,enumerable: true,configurable: false }
console.log(person.salary);//10000
console.log(pserson.luck);//good
person.promote = 1;
console.log(person.salary);//13000
//对象标签 对象序列化
/**
* [[proto]]
* [[class]]
* [[extensible]]
*/
//[proto] 原型
//Object.prototype
//[class] 类型
var toString = Object.prototype.toString;
function getType(o){
return toString.call(o).slice(8,-1)
};
console.log(toString.call(null));//'[Object Null]'
console.log(getType(null));//"Null"
console.log(getType(undefined));//"Undefined"
console.log(getType(1));//"Number"
console.log(getType(new Number(1)));//"Number"
console.log(typeof new Number(1));//"object"
console.log(getType(true));//"Boolean"
console.log(getType(new Boolean(true)));//"Boolean"
//extensible 对象是否可扩展
var obj = {x:1,y:2};
console.log(Object.isExtensible(obj));//true
Object.preventExtensions(obj);//阻止对象继续扩展属性
console.log(Object.isExtensible(obj));//false
obj.z = 1;
console.log(obj.z)//undefined 因为对象此时不可扩展
var a = Object.getOwnPropertyDescriptor(obj,'x');
console.log(a);//{ value: 1, writable: true, enumerable: true, configurable: true }
Object.seal(obj);//seal 会将对象上所有的属性的configurable设置为false
var b = Object.getOwnPropertyDescriptor(obj,'x');
console.log(b);//{ value: 1, writable: true, enumerable: true, configurable: false }
console.log(Object.isSealed(obj));//true 判断对象的属性是否被seal
Object.freeze(obj);//freeze 将对象属性设置为不可写
var c = Object.getOwnPropertyDescriptor(obj,'x');
console.log(c);//{ value: 1, writable: false, enumerable: true, configurable: false }
console.log(Object.isFrozen(obj));//true 判断对象的属性是否被freeze
//冻结对象时候并不会影响对象的原型链
//序列化 其他对象方法
var obj = {x:1,y:true,z:[1,2,3],nullVal:null};
var jsonStr = JSON.stringify(obj);
console.log("json字符串:"+jsonStr);//json字符串:{"x":1,"y":true,"z":[1,2,3],"nullVal":null}
obj = {val:undefined,a:NaN,b:Infinity,c:new Date()};//undefined值的属性不会出现序列化字符串中,NaN和Infinity 会变成null
jsonStr = JSON.stringify(obj);
console.log("json字符串2:"+jsonStr);//son字符串2:{"a":null,"b":null,"c":"2018-03-13T08:06:32.183Z"}
//json 数据变为对象
obj = JSON.parse('{"x":1}');
console.log(obj.x);//1
//自定义序列化 在对象属性中设置'toJSON'方法
var obj = {
x:1,
y:2,
o:{
o1:1,
o2:2,
toJSON:function(){
return this.o1 + this.o2;
}
}
}
var jsonStr = JSON.stringify(obj);
console.log(jsonStr);//{"x":1,"y":2,"o":3}
//toString 和 valueOf
var obj = {x:1,y:2};
console.log(obj.toString());//[object Object]
obj.toString = function(){
return this.x + this.y;
};
console.log("Result" + obj);//Result3
console.log(+obj);//3 from toString
//valueOf 尝试把对象转换为基本类型的时候回执行的方法 比toString方法优先级高
obj.valueOf = function(){
return this.x + this.y + 100;
};
console.log(+obj);//103 from valueOf
console.log("Result" + obj);//Result103 因为有valueOf
数组
- 数组概念
- 创建数组、数组增删改查操作
- 二维数组、稀疏数组
- 数组方法
- 数组 VS 一般对象
- 数组 VS 字符串
数组和一般对象的异同
- 相同点:都可以继承 数组是对象 对象不一定是数组 都可以当做对象添加和删除属性
- 不同点:数组自动更新length 按索引访问数组常常比访问一般对象属性明显迅速 数组对象继承
Array.prototype
上的大量数组操作方法
/**
* JS中的数组是弱类型的,数组中可以含有不同类型的元素,元素甚至可以是对象或其他数组
*/
var arr = [1,true,null,undefined,{x:1},[1,2,3]];//字面量创建方式
console.log(arr[5][1]);
//创建数组的方式
//1. 字面量方法
var BAT = ['Alibaba','Tencent','Baidu'];
var students = [{name:'Bosn',age:27},{name:'Nunnly',age:3}];
var arr = ['Nunnly','is','big','keng','B',123,true,null];
var arrInArr = [[1,2],[3,4,5]];
var commasArr1 = [1,,2];
console.log(commasArr1[1]);//undefined
var commasArr2 = [,,];
console.log(commasArr2[0]);//undefined
//2. Array构造器创建数组 new是可以省略的
var arr = new Array();
var arrWithLength = new Array(100);
var arrLikesLiteral = new Array(true,false,null,1,2,"hi");//等价于[true,false,null,1,2,"hi"]
//数组元素的读写
var arr = [0,1,2,3,4,5];
console.log(arr[1]);//1
console.log(arr.length);//6
console.log(arr);//[0,1,2,3,4,5]
arr[6] = 6;
console.log(arr.length);//7
delete arr[0];//删除第0个元素
console.log(arr.length);//7
console.log(arr);//[ <1 empty item>,1,2,3,4,5,6]
console.log(arr[0]);//undefined
//数组元素的增删 (JS中的数组是动态的 不需要指定大小)
var arr = [];
arr[0] = 1;
arr[1] = 2;
arr.push(3);//在数组尾部添加元素
console.log(arr);//[ 1, 2, 3]
arr[arr.length] = 4;//相当于 arr.push(4);
console.log(arr);//[ 1, 2, 3, 4]
arr.unshift(0);//在数组头部添加元素
console.log(arr);//[ 0, 1, 2, 3, 4]
delete arr[2];
console.log(arr);//[ 0, 1, <1 empty item>, 3, 4 ]
console.log(arr.length);//5
console.log(2 in arr);//false
arr[3] = undefined;
console.log(arr);//[ 0, 1, <1 empty item>, undefined, 4 ]
console.log(3 in arr);//true
arr.length -= 1;
console.log(arr);//[ 0, 1, <1 empty item>, undefined ]第四个元素被删除
arr.pop();//相当于length - 1 将数组尾部的元素删除
console.log(arr);//[ 0, 1, <1 empty item> ] 第三个元素被删除
arr.shift();//删除数组头部的元素
console.log(arr);//[ 1, <1 empty item> ]
//数组迭代
var i = 0, n = 10;
var arr = [1,2,3,4,5];
for(; i < n; i++){
console.log(arr[i]);//1,2,3,4,5,undefined,undefined,undefined,undefined,undefined
}
for(i in arr) {
console.log(arr[i]);//1,2,3,4,5
}
//forin是遍历的对象的属性 所以在原型链上加上属性x 也会打印出来
Array.prototype.x = 'inherited';
for(i in arr) {
console.log(arr[i]);//1,2,3,4,5,inherited
}
//过滤原型链上的属性
for(i in arr) {
if(arr.hasOwnProperty(i)){
console.log(arr[i]);//1,2,3,4,5
}
}
//二维数组
var arr = [[0,1],[2,3],[4,5]];
var i = 0, j = 0;
var row;
for(;i<arr.length;i++){
row = arr[i];
console.log('row' + i);
for(j=0;j<row.length;j++){
console.log(row[j]);
}
}
//打印结果 row0 0 1 row1 2 3 row2 4 5
//稀疏数组 (并不含有从0开始的连续索引,一般是length属性值比实际元素个数大) 在实际应用中并不常见
var arr1 = [undefined];
var arr2 = new Array(1);
console.log(0 in arr1);//true 因为有值 虽然是undefined
console.log(0 in arr2);//false 因为数组中并没有值
arr1.length = 100;
arr1[99] = 123;
console.log(99 in arr1);//true
console.log(98 in arr);//false
var arr = [,,];//也相当于一个稀疏数组
console.log(0 in arr);//false
//数组方法
//1. join (将数组转换为字符串)
var arr = [1,2,3];
console.log(arr.join());//1,2,3
console.log(arr.join("_"));//1_2_3
function repeatString(str,n){
return new Array(n + 1).join(str);
}
var string = repeatString("a",3);
console.log(string);//aaa
console.log(repeatString("Hi",5));//HiHiHiHiHi
//2. reverse (将数组逆序) (会将原数组修改)
var arr = [1,2,3];
arr.reverse();
console.log(arr);//[ 3, 2, 1 ]
//3. sort (排序) (原数组会被修改)
var arr = ["b","d","a","c"];
console.log(arr.sort());//[ 'a', 'b', 'c', 'd' ]
arr = [13,24,51,3];//会将元素转化为字符串然后再排序 并不会按照数字大小排列
console.log(arr.sort());//[ 13, 24, 3, 51 ]
//按照数字大小排列方法
arr.sort(function(a,b){
return a - b;
});
console.log(arr);//[ 3, 13, 24, 51 ]
//排列对象元素
arr = [{age:25},{age:39},{age:99}];
arr.sort(function(a,b){
return a.age - b.age;
});
arr.forEach(function(item){
console.log('age',item.age);
});
//输出 age 25 age 39 age 99
//4. concat (数组合并)(不会修改原数组)
var arr = [1,2,3];
var newArr = arr.concat(4,5);
console.log(newArr);//[ 1, 2, 3, 4, 5 ]
console.log(arr);//[ 1, 2, 3 ]
newArr = arr.concat([10,11],13);//会将元素都取出后再合并
console.log(newArr);//[ 1, 2, 3, 10, 11, 13 ]
newArr = arr.concat([1,[2,3]]);//只能取出一层 所以参数是数组并且里边的元素还有数组的话 合成的数组会带有数组元素
console.log(newArr); //[ 1, 2, 3, 1, [ 2, 3 ] ]
//5. slice (返回数组的一个片段)(不会修改原数组)
var arr = [1,2,3,4,5];
var newArr = arr.slice(1,3);
console.log(newArr);//[ 2, 3 ]
console.log(arr);//[ 1, 2, 3, 4, 5 ]
newArr = arr.slice(1);//第二个元素省略会从第一个参数的下标取到最后
console.log(newArr);//[ 2, 3, 4, 5 ]
newArr = arr.slice(1,-1);//-1代表取到倒数第二个元素
console.log(newArr);//[ 2, 3, 4 ]
newArr = arr.slice(-4,-3);
console.log(newArr);//[ 2 ]
//6. splice (数组拼接)(会对原数组进行修改)
var arr = [1,2,3,4,5];
var newArr = arr.splice(2);//第一个参数代表从什么地方开始截取
console.log(newArr);//[ 3, 4, 5 ]
console.log(arr);//[ 1, 2 ]
arr = [1,2,3,4,5];
newArr = arr.splice(2,2);//第二个参数代表将要删除的元素的个数
console.log(newArr);//[ 3, 4 ]
console.log(arr);//[ 1, 2, 5 ]
arr = [1,2,3,4,5];
newArr = arr.splice(1,1,'a','b');//可以追加参数 从删除的位置开始添加进去
console.log(newArr);//[ 2 ]
console.log(arr);//[ 1, 'a', 'b', 3, 4, 5 ]
//7. forEach
var arr = [1,2,3,4,5];
arr.forEach(function(x,index,a){
console.log(x+"|"+index+"|",+(a===arr)+"\n");
});
//打印结果
// 1|0| 1
// 2|1| 1
// 3|2| 1
// 4|3| 1
// 5|4| 1
//8. map (数组映射) (不会修改原数组数据)
var arr = [1,2,3];
var newArr = arr.map(function(x){
return x + 10;
});
console.log(newArr);//[ 11, 12, 13 ]
console.log(arr);//[ 1, 2, 3 ]
//9. filter (数组过滤) (不会修改原数组数据)
var arr = [1,2,3,4,5,6,7,8,9,10];
var newArr = arr.filter(function(x,index){
return index%3===0 || x>=8;
});
console.log(newArr);//[ 1, 4, 7, 8, 9, 10 ]
console.log(arr);//[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
//10. every&some (数组判断) every表示每一个元素都要符合指定的条件 some表示只需要有一个元素符合就可以
var arr = [1,2,3,4,5];
var b = arr.every(function(x){
return x < 10;
});
console.log(b);//true
var b1 = arr.every(function(x){
return x < 3;
});
console.log(b1);//false
var arr = [1,2,3,4,5];
var b2 = arr.some(function(x){
return x === 3;
});
console.log(b2);//true
var b3 = arr.some(function(x){
return x === 100;
});
console.log(b3);//false
//11. reduce & reduceRight reduce是将数组中的元素两两之间执行特定的操作
var arr = [1,2,3];
var sum = arr.reduce(function(x,y){
return x + y;
},0);
console.log(sum);//6
console.log(arr);//[ 1, 2, 3 ]
arr = [3,9,6];
var max = arr.reduce(function(x,y){
console.log(x + "|" + y);
return x > y ? x : y;
});
//3|9
//9|6
console.log(max);//9
//reduce 是从左往右 reduceRight是从右往左
max = arr.reduceRight(function(x,y){
console.log(x+"|"+y);
return x > y ? x : y;
});
//6|9
//9|3
console.log(max);//9
//12. indexOf & lastIndexOf (数组检索,检索元素在数组中的位置)
//indexOf是从左往右查 lastIndexOf是从右往左查
var arr = [1,2,3,2,1];
console.log(arr.indexOf(2));//1
console.log(arr.indexOf(99));//-1 没有回返回-1
console.log(arr.indexOf(1,1));//4 从第二个元素开始查找
console.log(arr.indexOf(1,-3));//4
console.log(arr.indexOf(2,-1));//-1
console.log(arr.lastIndexOf(2));//3 从右往左查找
console.log(arr.lastIndexOf(2,-2));//3
console.log(arr.lastIndexOf(2,-3));//1
//11. Array.isArray(Object) 判断是否为数组
var arr = [1,2,3];
console.log(Array.isArray(arr));//true
//还可以用以下方法判断对象是否为数组
console.log(arr instanceof Array);//true
console.log(({}).toString.apply(arr));//[object Array]
console.log(arr.constructor === Array);//true
//字符串和数组 字符串是一种类似数组但不是数组的对象
var str = "hello world";
console.log(str.charAt(0));//h
console.log(str[1]);//e
var a = Array.prototype.join.call(str,"_");
console.log(a);//h_e_l_l_o_ _w_o_r_l_d