JavaScript深入浅出(进阶)

1、数据类型

js是弱类型,定义变量时不需要指定具体的数据类型,因此会出现一些奇妙的事情:

var num=23;   ---number类型
num="23";     ---string类型
"23" + 23 ;   结果为2323,string类型[字符串的连接
"23" - 23     结果为0,number类型[如果有一个操作数是字符串,先将其转换为数值,再执行减法运算]

六种数据类型:

1)原始类型:number、string、boolean、undefined、null  

2)对象:object( Function、Array、Date...)


2、隐式类型转换

若要将string->number :   - 0 (减去 0)

number -> string :   + ''  (加上空串'')


3、包装对象

 var str = "string" ;  ---string类型
 var strObj= new String(" string" ); ---String类型
为什么string类型可以有属性(如length)? 因为在调用时系统自动将其转换为object类型,结束后销毁(还原)

 

4、类型检测

1) typeof

2) instanceof ---obj instane Object

[2,3] instanceof Array === true


 

3) Object.prototype.toString

 

Object.prototype.toString.apply([]) === "[objectArray]"

4)constructor

5) duck type         适用参考来源       类型转换超难【不会】例子


5、运算符      来源

1) ,逗号运算符:从左往右依次运算,结果为最右边的运算值

2) delete运算符:删除值 

3)  in/

6、语句

1) 在for(var i=0)中定义的i是全局变量,不是块级作用域

2) try catch/finally

3) 函数声明: var fun=function(){ ...//}   function fun(){   ...//变量提升,会 先执行 } 

4) for in 受原型链影响: var p; var obj={x:1 , y:3};   for( p  in  obj)

5) with 修改作用域

6) 'use strict' 严格模式



7、对象

1)定义

方式一: var obj={x:1 ,y:2 ,z:{a:1 ,b:2} };
方式二(  new/原型链 )

2)对象结构



3)原型链当定义一个函数(function fun),都会自动有一个原型属性(prototype)



当定义一个新的对象时,在本对象查找不到属性,会沿着原型链往上查找

 

方式三( Object.create):  var obj=Object.create({x:1 ,y:2});

 

4)属性操作 :  读写对象属性、属性异常、删除属性、检测属性、枚举属性

<1>属性读写方式一:

var obj={x:2 ,y:3};
obj.x;  --2    //两种方式
obj["y"]; ---3

<2>属性读写异常


<3>属性删除:delete obj.x ;

<4>属性检测:son in obj ;   ---返回true/false    (会沿着原型链向上查找)

  obj.hasOwnProperty(" son");  ---自身对象

  obj.propertyIsEnumberable(" son");  ---是否可以被枚举

  Object.defineProperty( obj , "son" ,{ enumerable : true ,value : 23} );   ---定义属性和原型链上的属性

-obj.hasOwnProperty(" son");  ---自身对象
obj.propertyIsEnumberable(" son");  ---是否可以被枚举
Object.defineProperty( obj , "son" ,{ enumerable : true ,value : 23} );  ---定义属性和原型链上的属性  参数:对象,属性,原型链上的属性
  一知半解:移驾

属性读写方式二:getter/setter

var person={ name:"cheng" ,get age(){  return 23;} ,set age(val){  ..}  };
console.log(person.age);   ---23  自动调用get age()方法 

 

5)属性标签:

Object.getOwnPropertyDescriptor( { obj: ' test'} , "obj" ) ;   ---参数: 对象,属性

 


对象标签:[[ proto ]] 、[[ class ]] 、[[ extensible ]]

<1>原型标签 [[ proto ]]

<2>对象类型标签[[ class ]] 

var toString=Object.prototype.toString;
function getType(obj){ return toString.call(obj).slice(8,-1);  } 
 //调用获取对象类型的方法,并截取其中的有效数据 , 从第8位开始倒数第2位(去掉[object ])
toString.call(null);  ---"[object Null]"
getType(null); 	 ---"Null"
getType(1);  ---"Number"

<3>对象(的属性)可扩展标签 extensible 

object.preventExtensible(obj);	//使obj对象不可新增属性,原属性可改、可删
Object.seal(obj);	//使obj不可新增属性,原属性可改但不可删
Object.freeze(obj);	//使obj不可新增属性,原属性不可更改、删除


6)序列化:将数据变为字符串形式
var obj={ x:1 ,y: true ,z: [1,2,3] ,t: undefined }; 
JSON.stringify(obj);    //将js对象序列化---后端 可用
//   "{ "x" :1 , "y" :true ,"z" :[1,2,3] } "   --undefined直接被舍弃
obj=JSON.parse( '{"x":1 }' );   // obj.x=1  ,将字符串转化为js对象

序列化自定义
var obj = {
    x : 1,
    y : 2,
    o : {
        o1 : 1,
        o2 : 2,
        toJSON : function () {
            return this.o1 + this.o2;
        }
    }
};
JSON.stringify(obj); // "{"x":1,"y":2,"o":3}"



8、数组


1)值的有序集合。弱类型,每个值可以是不同的类型。也可以是数组

var obj=[ 1, null ,true ,[3,2] ];   ---obj[3][1]=2  

2)创建  

 var arr=[1,,3];  var  arr=[1,,];   ---空为undefined ,默认最后一个可为,
 var arr2 = new Array(100);  ---创建100个空值数组
  var arr2 = new Array(1,2,3) ;  ---值为1,2 ,3

3)读写

var arr=[1,3];
arr[2]=true;  ---动态添加第三个数true 
arr.length=3;
delete arr[0];  --删除第一个数据,变为空值"",数组长度不变
arr.length-=1;  //通过将数组长度-1,可以动态删除最后一个数据
arr.push(23);  最后位置插入一个值23 
var lastNum=arr.pop();  最后一位数据删除并返回
arr.unshift(23);  首部位置插入一个值23
var firstNum=arr.shift();  第一位数据删除并返回



4)二维数组

var arr=[[1,2],[2,3],[3,4,5]];
for(var i=0;i<arr.length;i++){
	var arr2=arr[i];
	for( var j=0;j<arr2.length;j++){
		console.log(arr2[j]);
	}
}

5)稀疏数组:不含有从0开始的连续索引,一般length值比实际元素个数大

var arr1 = [undefined];
var arr2 = new Array(1);
0 in arr1; // true			var arr=[,,];
0 in arr2; // false			0 in arr; //false
arr1.length = 100;		
arr1[99] = 123;
99 in arr1; // true
98 in arr1; // false


6)数组方法--原型方法 Object.prototype


var arr=[1,2,3];
arr.join("_");  ---转化为字符串,有参数则为连接符  :1_2_3  ;无参即为 1,2,3
例:function repeatString(str, n) {	//快速定义一个重复数组的字符串
     return new Array(n + 1).join(str);  	//长度为n+1,中间的连接为n个
}    
repeatString("a", 3); 	// "aaa"	[undefined,undefined,undefined,undefined]		
repeatString("Hi", 5); 	// "HiHiHiHiHi"

arr.reverse();  ---反序排列数组  : 3,2,1 (原数组被修改)

arr.sort();  ---字母顺序排序
var arr = ["a", "d", "c", "b"];
arr.sort(); 	// ["a", "b", "c", "d"]

arr = [13, 24, 51, 3];
arr.sort(); // [13, 24, 3, 51]	
arr;	 // [13, 24, 3, 51]  ---将第一个去做了比较

arr.sort(function(a, b) {   //自定义排序函数	         	//带参数的排序w3c来源
     return a - b;	
}); 	// [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);
});
// result:	 age 25、age 39、age 99

arr.concat(2,3);  --数组合并
var arr = [1, 2, 3];
arr.concat(4, 5); // [1, 2, 3, 4, 5]
arr; // [1, 2, 3]   ---原数组没有被修改

arr.concat([10, 11], 13); // [1, 2, 3, 10, 11, 13] --参数是数组,会被拉平一次 
arr.concat([1, [2, 3]]); // [1, 2, 3, 1, [2, 3]

arr.slice(2,5);  --数组截取 ,参数为索引, [2,5) ,最后一位索引也是 -1
var arr = [1, 2, 3, 4, 5];
arr.slice(1, 3);   // [2, 3]      --原数组没有被修改

arr.slice(1); 	  // [2, 3, 4, 5]
arr.slice(1, -1);   // [2, 3, 4]
arr.slice(-4, -3);   // [2]

arr.splice(2);  --数组拼接/删除 
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.splice(2);   // returns [3, 4, 5]
arr;   // [1, 2];	--原数组被修改

arr = [1, 2, 3, 4, 5];
arr.splice(2, 2); // returns [3, 4]	参数:索引,想删除的元素个数
arr;   // [1, 2, 5];

arr = [1, 2, 3, 4, 5];
arr.splice(1, 1, 'a', 'b'); //returns [2] 参数:第三个开始是要添加的值,再删除的位置开始添加、拼接
arr;    // [1, "a", "b", 3, 4, 5]

arr.forEach( function( x , index){  ...} );  --数组遍历  函数为参数,x为值、index索引  IE 9+
var arr = [1, 2, 3, 4, 5];
arr.forEach(function(x, index, a){
    console.log(x + '|' + index + '|' + (a === arr));
});
// 1|0|true			// 2|1|true			// 3|2|true
// 4|3|true			// 5|4|true

arr.map( function(x) {  ...} );  ---数组映射,在数组的基础上做一些变动  函数为参数,x为值
var arr = [1, 2, 3];
arr.map(function(x) {
     return x + 10;
}); 	// [11, 12, 13]
arr; 	// [1, 2, 3] --原数组没有被修改

arr.filter( function( x , index){  ...} );  --数组过滤、筛选  函数为参数,x为值、index索引
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.filter(function(x, index) {
     return index % 3 === 0 || x >= 8;
}); 	// returns [1, 4, 7, 8, 9, 10]
arr; 	// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ---原数组没有被修改

arr.every/some( function(x) {  ...} ); 
	//数组判断,是否符合条件,every代表每一个值(x);some代表至少存在一个值满足条件
var arr = [1, 2, 3, 4, 5];        var arr = [1, 2, 3, 4, 5];
arr.every(function(x){		   arr.some(function(x) {
   return x<10;  			return x === 3;
});  //true			   });  // true


arr.every(function(x){		   arr.some(function(x) {
   return x<3;  			return x === 100;
});  //false			   });  // false

arr.reduce/reduceRight( function(x) {  ...} );   数组中的值两两进行操作、判断
var arr = [1, 2, 3];
var sum = arr.reduce(function(x, y) {
     return x + y; 	 //第一个参数为函数,第二个为第一个参数的x;若没有,则x是数组第一个数,
}, 0); // 6								       y为第二个数
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     9	max; // 9
max = arr.reduceRight(function(x, y) {      //判断的顺序从后 往前
     console.log(x + "|" + y);
     return x > y ? x : y;
});
// 6|9	     9|3	max: 9

arr.indexOf/lastIndexOf(3);   //数组检索 ,last..从后往前找,返回的都是坐标(最后一位索引-1 )
var arr = [1, 2, 3, 2, 1];
arr.indexOf(2); 	// 1   --查找2
arr.indexOf(99); 	// -1    --没找到
arr.indexOf(1, 1); 	// 4  --查找1,从索引1(第二个数)开始查找
arr.indexOf(1, -3); 	// 4
arr.indexOf(2, -1); 	// -1
arr.lastIndexOf(2); 	// 3
arr.lastIndexOf(2, -2); 	// 3
arr.lastIndexOf(2, -3); 	// 1

Array.isArray([]);   true  ---判断是否为数组
[] instanceof Array; // true
({}).toString.apply([]) === '[object Array]'; // true
[].constructor === Array; // true


数组与字符串
var str = "hello world";
str.charAt(0); // "h"	
str[1]; // e   	--一般不用这样(数组方法操作字符串)

Array.prototype.join.call(str, "_");  //利用数组方法操作字符串
// "h_e_l_l_o_ _w_o_r_l_d"

9、函数(对象)

js中,函数也是对象,可以像其他对象操作与传递。

1)调用:
<1>直接调用:foo();
<2>对象方法:o.method();
<3>构造器:new Foo();
<4>call/apply/bind : func.call( o );

2)定义: 
<1>函数声明方式: 
function fun(){  ...};     //作用全局,声明会提前到最开始

<2>函数表达式方式:    ---具体移驾
var fun=function(){  ...};   //函数变量
(function(){  ...})();      //立即执行
return function(){  ...};   //作为返回值
var fun=function another(){  ...};  //命名式函数

<3>函数构造器
var fun = new Function('a','b',' console.log(a+b); ');   //fun(1,2);   =3
var fun = Function('a','b',' console.log(a+b); ');  //最后一个为函数体,前面都是参数

10、this    我也还不懂

1)全局的this---浏览器
this.document===document;
this===window
this.a=37;
window.a ;    ---37

2)一般函数的this---浏览器
function fun(){   return this; }   fun()===window;   --严格模式下为undefined

3)作为对象方法的函数 this---对象

4)作为对象原型链上的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() );   //5  --this 可以取到 p.a  

5)get/set 与 this

6)构造器中的this


7)call/apply方法的this



8)bind方法与this      


11、函数属性和arguments   --bind/call/arguments


1) fun.name 函数名

2) fun.length 形参个数

3) arguments.length 实参个数


12、闭包   ---参考:详解



13、作用域






14、OOP--面向对象编程


1) 基于原型的继承:每个 函数(对象)声明后都有一个原型属性:prototype
2) 原型和prototype属性:prototype是每个对象都会有的一个属性,通过这个属性可以有很多的方法














  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芒果-橙

谢谢啦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值