JavaScript 数据类型、面向对象编程


 

数据类型

基本数据类型

  • string 单双引均可
  • number 数值型
  • boolean
  • null
  • undefined 未定义(已声明、未赋值)

复杂数据类型:object。object又可细分为以下2种

  • Array 数组
  • Object 对象

检测数据类型的两种⽅法

  • typeof(xxx) 复杂数据类型显示为object
  • Object.prototype.toString.call(xxx) 专用于检测复杂数据类型(引用类型),会显示object具体的类型(Object、Array)
console.log(typeof(""));  // string
console.log(typeof(1));  // number

console.log(Object.prototype.toString.call({}))  // [object Object]
console.log(Object.prototype.toString.call([]))  // [object Array]

 

变量

var i;  //只声明未赋值,类型是undefined

var j=10;  //js的变量是弱类型的,根据值来确定变量类型

j="ok";  //js变量的数据类型可变

变量标识符

  • 可以包含英文字母A-Za-z、数字0-9、下划线_、美元符号$
  • 不能以数字0-9开头

js区分大小写,username、userName是2个不同的变量

 

类型转换

显式转换

//转换为数值,常用于获取数值型输入框的值,在提交之前做一些处理、校验
var a;
a=Number("1.6");  //转换为数值,如果不能转换为数值,不会报错,转换结果是NaN,即Not a Number
a=parseInt("1.6"); //转换为整型,直接舍弃小数部分
a=parseFloat("1.6"); //转换为浮点型


//转换为字符串
var b=1.4;
b=b.toString();
b=String(1.2);


//转换为boolean
var c=Boolean(0);

 
隐式转换:自动完成类型转换

a=1.2+"";  //字符串拼接。如果有一个加数是字符串,会自动将其它加数转换为字符串,再进行运算


if(12=="12"){ //相等判断时,如果一方是字符串,会自动先将另一方转换为字符串,再进行判断
	console.log("true")
}	

 

字符串常用方法

var str = "hello";

str.length  //获取字符串长度


str.indexOf("he")  //返回首次出现的位置,下标
str.lastIndexOf("he")  //indexOf是从前往后找,lastIndexOf是从后往前找,返回的都是索引(正数),未找到则返回-1
str.indexOf("he",2)  //2个方法均可指定检索的起始位置

str.search("he")  //search的作用和indexOf相同,但不能指定检索的起始位置


// 以下3个方法均用于返回子串

// [start,end),缺省end时默认提取到末尾
str.slice(2,3)  //可使用负数索引。但低版本IE(<9.0)不支持负数索引
str.substring(2,3)  //不能使用负数索引

// (start,length),第二个参数是提取长度
str.substr(2,1)


// 替换子串。不改变原串,以新串的形式返回
str.replace("he", "He")  //默认只替换第一个匹配到的,区分大小写
str.replace(/he/i, "He")  //正则表达式,i不区分大小写。注意正则表达式不引
str.replace(/he/g, "He")  //g替换所有匹配
str.replace(/he/ig, "He")  //i、g可一起使用


// 连接1个或多个字符串,以新串形式返回,不改变原串
str.concat(" ","js")


// 去除2端的空白符
str.trim()  


// 转换为全大|小写
str.toUpperCase()
str.toLowerCase()


// 返回指定位置上的字符
str.charAt(2)

js的字符串是不可变的,所有修改字符串的操作,都是以新串形式返回,原串不改变。

search()、indexOf()、lastIndexOf()、replace()常结合正则表达式使用,注意正则表达式不引。

 

数值型常用方法

var n = 9.656;

// 保留指定位数的小数,返回字符串
n.toFixed(0)  //0即取整
n.toFixed(2)  //保留2位小数


// 保留指定位数(整数+小数),返回字符串
n.toPrecision();  //不指定默认保留全部位数
n.toPrecision(2);  //保留2位数字

会自动四舍五入,位数不够时自动在末尾补0。返回的是字符串,不改变变量的值。

 

数组

数组的创建、赋值
// 直接创建
var arr1=[];  //创建空数组
var arr2=[1,2,3,4];  //创建数组并初始化


// 使⽤构造函数创建
var arr3 = new Array();  //创建空数组
var arr4 = new Array(2); //创建⼀个初始长度为10的数组。如果参数个数=1,该参数是数组的初始长度
var arr5 = new Array(1,2,3,4); //如果参数个数>1,参数是数组元素


// 数组元素的赋值、获取
arr5[0]=10; 
console.log(arr5[0]);

js数组的长度会动态变化,指定的初始长度只是创建数组时预先分配空间,后续空间不够时会自动扩容。

js数组中的元素,类型可以不同,因为js是弱类型的,本身不太区分类型。

 

数组常用方法
var arr1=[1,2,3,4];

//添加元素
arr1.unshift(10, 20);  //在数组开头(第一个元素之前)添加1个或多个元素,返回添加后的数组长度
arr.push(5, 6);  //在数组末尾添加1个或多个元素


//删除元素
arr1.shift();  //删除并返回数组的第一个元素
arr1.pop();  //删除并返回数组的最后⼀个元素



//连接数组
var arr2=[10,11,12];
var arr3=[20,21];

arr1.concat(arr2);  //不改变原数组,以新数组的形式返回
arr1.concat(arr2,arr3);  //参数可以是一个或多个数组



// 数组转字符串
arr1.join();  //连接数组元素,返回字符串
arr1.join("_");  //可指定连接符,缺省时默认为逗号


// 字符串转数组
var str="c c++ java";
str.split();  //不指定切割福,默认整个字符串作为一个元素,["c c++ java"]
str.split(" ");  //指定切割符,["c","c++","java"]
str.split(" ",2);  //指定数组中要保留的元素个数,["c","c++"],不指定时默认全部保留


// 数组反序,原数组改变
arr1.reverse();  



//元素排序,原数组改变
arr1.sort();  //默认按ASCII码值升序排列,逐字符比较,eg. [21,204] => [204,21],第一个字符相同,第二个:1的ASCII码比0大
arr1.sort(function(a,b){  //自定义排序方式
  // return a-b;  //按数值大小升序排列
  return b-a;  //按数值大小降序排列
});


/*
获取数组片段,以新数组形式返回,原数组不变
[start,end),2个参数均为数组下标,均可以使用负数,-1表示最后一个元素,-2表示倒数第二个元素
start必需,end可选,缺省end默认到末尾
*/
arr1.slice(1,3); 


//返回数组中第一次出现该元素的位置,如果数组中没有该元素,返回-1
arr1.indexOf("go", 0);
//第二个参数指定检索开始位置,可选,缺省时默认为0(从第一个元素开始)
arr1.indexOf("go");


//先删除再在该位置插入元素,参数依次是:start 起始位置、deleteCount 要删除的元素个数、ele... 要添加的元素(个数可变),会添加在指定的起始位置之后
arr1.splice(1, 2, "go", "rust");
//只有2个参数,表示只删除,不插入,搭配 indexOf()可删除指定元素
arr1.splice(2, 1)
//第二个参数为0,表示不删除、只插入
arr1.splice(2, 0, 20, 30)

 

数组迭代
var arr = [45, 4, 9, 16, 25];

// 使用for循环迭代数组
for(var i=0; i<arr.length; i++){
	console.log(arr[i]);
}


//使用forEach迭代数组,参数是函数
//函数的参数个数可选,但顺序是固定的,依次是元素、索引、数组本身
arr.forEach(function(ele, index, arr){
	console.log(index + "-----" + ele);
});

// ES6的箭头函数写法
arr.forEach(ele => {
	console.log(ele);
});

forEach不能使用break结束循环,建议只把forEach用于需要遍历完所有元素的迭代。

 

对象

对象的创建、使用
//直接创建
var obj1={};  //创建空对象
var obj2={name:"chy",age:20};  //创建对象并初始化


// 使⽤构造函数创建
var obj3=new Object();  
var user=new Object({name:"chy",age:20});


// 获取属性的值
console.log(user.name);

// 设置属性的值,如果key不存在则为添加,如果key已存在则为更新
user.name="zhangsan";

//删除属性(键值对)
delete(user.name);

创建对象之前不需要指定对象有哪些属性,创建对象时也不需要指定全部的属性,创建对象后可以 xxx.xxx 直接设置|访问属性,包括创建时没有设置过的属性,js 就是这么随心所欲。

对象的key只能是字符串,引不引都可以,都是作为字符串处理。

 

遍历对象的属性
let user = {"name":"chy","age":20}

// 实质是遍历对象的key
for (let key in user) {
    let value = user[key] // user[key] 可以解析[]中的变量,user.key 直接把key作为字符串字面量、不会作为变量解析
    console.log(value)
}

for in是Object遍历属性的方式,数组继承了Object,可以使用for in遍历数组,但毕竟不是专门的数组遍历方式,容易踩坑,不推荐使用for in遍历数组。

 

操作对象属性的2种方式
//方式一、通过.来操作,只会把点号后面的属性名作为字符串常量处理
user.name  //如果name是变量,也是作为字符串"name"来处理,不会替换为对应的值


//方式二、通过[]来操作,[]中可以使用字符串常量,也可以使用变量
user["name"]  //[字符串常量]

var key="name";
user[key]  //[变量]

如果属性名要使用变量的值,则使用方式二。

 

快速置空对象各个字段的值
Object.keys(user).forEach(key => user[key] = '');

 

js 面向对象编程

面向对象的3大特性:封装、继承、多态

<script>
	// 创建对象
	var user=new Object();
	
	// 添加成员变量
	user.name="chy";
	user.age=20;
	
	// 添加成员方法
	user.getName=function(){
	  // 在对象内部访问成员变量、调用成员方法,需要使用对象名来操作,不能直接访问。因为现在是user.xxx在对象内部,所以也可以使用this表示当前对象
	  // return user.name;
	  return this.name;
	}
	
	user.getAge=function(){
	  // return user.age;
	  return this.age;
	}
	
	user.getInfo=function(){
	  // return user.name+"  "+user.age;
	  return this.name+"  "+this.age;
	}
	
	
	console.log(user);
	
	
	// 在对象外部可以通过对象名,访问对象的成员变量、调用成员方法
	console.log(user.name);
	console.log(user.info());
</script>

在js脚本中,对象的成员没有访问权限这一说法,在对象外部都可以访问对象的成员。

上面的写法有2个缺点

  • 成员变量的值写死了,虽然可以写set方法,在使用对象时先调用set方法给成员变量赋值,完成成员变量的初始化,但还是不够方便
  • 每次创建对象时都要添加成员,很麻烦

上面的方式基本不用,一般都是使用工厂函数

 

工厂函数

写法一

<script>
	function createUser(name,age){
		// 创建对象
		var user=new Object();
		
		// 添加成员变量
		user.name=name;
		user.age=age;
		
		// 添加成员方法
		user.getName=function(){
		  // return user.name;
		  return this.name;
		}
		
		user.getAge=function(){
		  // return user.age;
		  return this.age;
		}
		
		user.getInfo=function(){
		  // return user.name+"  "+user.age;
		  return this.name+"  "+this.age;
		}
		
		// 返回对象
		return user;
	}
	
	
	// 创建对象
	var user=createUser("chy",20);
	
	// 访问对象成员
	console.log(user.name);
	console.log(user.getInfo());

</script>

由工厂函数自己创建、返回对象

 

写法二

<script>
	function createUser(name,age){
	  // 添加成员变量
	  this.name=name;
	  this.age=age;
	
	  // 添加成员方法
	  this.getName=function(){
	    return this.name;
	  }
	
	  this.getAge=function(){
	    return this.age;
	  }
	
	  this.getInfo=function(){
	    return this.name+"  "+this.age;
	  }
	}
	
	
	// 创建对象
	var user=new createUser("chy",20);
	
	// 访问对象成员
	console.log(user.name);
	console.log(user.getInfo());

</script>

由 new 工厂函数() 自动完成创建对象、返回对象两步,不用在工厂函数中手动创建、返回对象。

工厂函数相当于构造函数。在工厂函数内部,this表示创建的对象,成员变量要用this,不用this则使用的是形参,不是成员变量。

 

写法三 (推荐)
用原型挂载方法

<script>
    function createUser(name,age){
      // 添加成员变量
      this.name=name;
      this.age=age;
    }

     // 使用原型挂载策成员方法。工厂函数名.prototype.方法名
     createUser.prototype.getName=function(){        
       return this.name;
     }

     createUser.prototype.getAge=function(){
       return this.age;
     }

     createUser.prototype.getInfo=function(){
       return this.name+"  "+this.age;
     }

    // 创建对象
    var user=new createUser("chy",20);

    // 访问对象成员
    console.log(user.name);
    console.log(user.getInfo());

</script>

写法二有一个缺点:每个对象都会创建自身的方法,调用对象的成员方法时都是调用每个对象自身的方法,浪费资源、没必要。

用原型挂载方法后,创建对象时不再创建成员方法,同一个工厂创建的对象共用同一个原型,通过对象调用方法时,自动把对象挂载到原型上,调用原型上的方法,得到相应的结果。

所谓原型,类似于其它语言中的类,是对象的模板,公共部分。

 

等价判断

==不区分数据类型,空串、空格串、0、空数组[ ]、false都是==的,注意不包括空对象{ }、null。

===严格区分数据类型。

  • 9
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值