1、js 中有几种数据类型
6种:
1、String
2、Number
3、Boolean
4、Null
5、Undefined
6、Object
(Object 是 引用数据类型,其他的是基本数据类型)
( .typeOf() 可以检测数据类型)
基本数据类型: 变量存在栈内存里面,值与值之间独立存在,修改一个变量不会影响别的变量。
引用数据类型: 变量存到堆内存里,每创建一个新对象就行再堆内存种开辟出一个新的空间,而变量保存的是内存地址。
// 列: (基本数据类型: 变量存在栈内存里面,值与值之间独立存在,修改一个变量不会影响别的变量。)
var a = 123;
var b = a;
a++
console.log(b) // 123
// 列: (引用数据类型: 变量存到堆内存里,每创建一个新对象就行再堆内存种开辟出一个新的空间,而变量保存的是内存地址。) Object;
var a = new
var b = a;
a.name = 'suzy'
console.log(b) // {name: "suzy"}
// 列:(比较2个对象时,即使属性名和属性值一样 但是)
var a = new Object;
var b = new Object;
a.name = 'suzy'
b.name = 'suzy'
console.log(b==a) // 123
2、数据类型转换
— 调用方法:
- toString()
var aa = 111;
aa.toString();
// null 和 underfind 没有 toString 方法
— 调用函数:
- String()
- Number()
- Boolean()
- parseInt() // 返回字符串中有效 整数 取出来转为Number
- parseFloat() // 返回字符串中有效 小数 取出来转为Number
var aa = 111;
String(aa); //'111'
var aa = '122px2';
console.log(parseInt(aa)) // 122
var aa = '1.221ad1';
console.log(parseFloat(aa)) // 1.221
// String(null) 返回 字符串'null'
// String(underfind) 返回 字符串'underfind'
// Number(true) 返回 1
// Number(false) 返回 0
// Number(undefined) 返回 NAN
// Number('') 返回 0
//parseFloat(true) 返回 NAN
//parseInt(true) 返回 NAN
//parseInt(undefined) 返回 NAN
//parseInt('') 返回 NAN
3、循环
— switch循环:
switch(表达式) {
case n:
代码块
break;
case n:
代码块
break;
default:
默认代码块
}
— for循环:
var cars = [1,2,3,4]
for (i = 0; i < cars.length; i++) {
console.log(cars[i])
}
— 阻止外层循环(label):
outer:
for (var i = 0; i < 5; i++) {
console.log('i', i)
for (var j = 0; j < 5; j++) {
console.log('j', j)
break outer
}
}
//"outer" 为循环的名称,可以在嵌套循环里面阻止外部循环。
5、js对象
// 检查一个对象种有没有某个属性
console.log('name' in obj2)
6、枚举对象中的属性 (for … in)
var obj = {
name:'22',
age:11
}
for (var n in obj) {
console.log(n) // name age
}
7、构造函数与原型对象
function MyClass(name) {
this.name = name
}
MyClass.prototype.sayName = function(){
return this.name
}
// 如果 sayName 方法写在构造函数里面的话会浪费内存, 调用几次 new MyClass 方法就会创建几个sayName函数。
var mc = new MyClass('suzy')
console.log(mc.__proto__ == MyClass.prototype) // true
console.log(mc.sayName()) // suzy
hasOwnProperty :判断自身是否有某个属性
8、数组
[ 8-1 ] : slice 与 splice
—— slice(start,end)
从start开始截取到end但是不包括end
返回值为截取出来的元素的集合
原始的数组不会发生变化
—— splice(start,deleteCount,item1,item2……);
start参数 开始的位置
deleteCount 要截取的个数
后面的items为要添加的元素
如果deleteCount为0,则表示不删除元素
这个方法会改变原始数组
[ 8-2] : 数组去重
方法一:
var newArr = [];
var arr = [1, 2,2, 3, 4,11, 5, 1, 2, 2, 2, 2, 2]
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) { // 重点是 :indexOf
newArr.push(arr[i])
}
}
console.log(newArr)
方法二:
var arr = [1, 2, 3, 3, 4, 5, 1, 2, 2, 2, 2, 2]
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1)
j-- // 重点是 :j--
}
}
}
[ 8-3] : 数组合并 :concat()
var arr = [1, 2, 3]
var arr2 = [4, 5, 6]
var arr3 = [7, 8, 9]
console.log(arr.concat(arr2, arr3)) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// concat 不会影响原数组
[ 8-4 ] : 数组转字符串:join()
var arr = [1, 2, 3]
console.log(arr.join('')) // 123
// concat 不会影响原数组
[ 8-5 ] : 数组反转:reverse()
var arr = [1, 2, 3]
console.log(arr.reverse()) // [3,2,1]
// concat 会影响原数组
[ 8-6 ] : 数组排序:sort()
var arr = [1, 2, 11, 3, 0]
arr.sort(function(a, b) {
return a - b
})
console.log(arr) // [0,1,2,3,11]
// concat 会影响原数组
8、Math
Math.PI // 3.141592653589793 圆周率
Math.ceil(22.6) // 23 向上取整
Math.floor(22.6) // 22 向下取整
Math.round(22.6) // 23 四舍五入
Math.random() // 0-1之间的随机数
Math.max(num,num1,num2) // 获取多个数中的最大值
Math.min(num,num1,num2) // 获取多个数中的最小值
Math.pow(x,y) // 返回x的y次幂
Math.sqrt(num) // 返回一个数的平方根
生成一个x-y之间的随机数:
// 随机数 - 公式
Math.round(Math.random()*(y-x))+x
Math.round(Math.random()*10) // 0-10之间的随机数
Math.round(Math.random()*9)+1 // 1-10之间的随机数
// pow 和 sqrt
console.log(Math.pow(9,2)) // 81
console.log(Math.sqrt(81)) //9
9、String 的方法
.slice(开始截取的索引,结束截取的索引) // 结束截取的索引 值为负数时 从反方向开始。
.substr(开始截取的索引,结束截取的索引)
.substring(开始截取的索引,截取的长度)
.charAt() // 返回指定位置的字符
.split() // 用于把一个字符串分割成字符串数组
.toUpperCase() // 将字符串转为大写
.toLocaleLowerCase() // 将字符串转为小写
10、正则表达式
1、邮件正则
new RegExp(pattern, attributes);
// 参数 pattern : 字符串(正则表达式)
// 参数 attributes : 可选的字符串 ("g"或"i" 分别用于指定全局匹配、区分大小写的匹配。)
格式
/*
* [ab] == a|b
* [a-z] 任意小写字母
* [A-Z] 任意大写字母
* [A-z] 任意字母
* [^0-9] 除了0-9除了数字
*/
列:
// 检查一个字符串中是否含有 abc 或 adc 或 aec
var reg = /a[bde]c/; // 也可以这样写:new RegExp('a[bde]c','i'), i 表示不区分大小写
console.log(reg.test('abcd')) //true
// 除了数字
var reg = new RegExp('[^0-9]','i')
console.log(reg.test('a')) // true
// split - 去掉字符串中的字母
var a = '1a2b3c4d5e6f7g8';
console.log(a.split(/[A-z]/).join('')) // 12345678
// search - 判断字符串中是否含有数字
var a = 'hello';
console.log(a.search(/[0-9]/)) // -1 (-1 表示没有,跟indexOf类似,不同的是 search 可以接收正则表达式)
// match - 将字符串中的字母提取出来(不分大小写:i , 全局匹配:g)
var a = 'ABC123abc';
console.log(a.match(/[a-z]/gi)) // [ABCabc]
// replace - 将字符串中的字母去掉
var a = 'ABC123abc';
console.log(a.replace(/[a-z]/gi,'')) // 123
// 量词:{n} - 检查字符串中是否有3个ab
var reg = /(ab){3}/; // (ab)是个整体
console.log(reg.test('ababababab')) // true
// 量词:{n} - 检查a和c之间是否正好有3个b
var reg = /ab{3}c/;
console.log(reg.test('abbbbc')) // false
// 量词:{m,n} - 检查a和c之间是否有1-3个b
var reg = /ab{1,3}c/;
console.log(reg.test('abbbc')) // true
// 量词:{n,} - 检查a和c之间是否有3个及3个以上的b
var reg = /ab{3,}c/;
console.log(reg.test('abbbc')) // true
// 量词:+ - 1个或多个,相当于{1,} (检查a和c之间至少有一个b )
var reg = /ab+c/; // 相当于 var reg = /ab{1,}c/
console.log(reg.test('abbc')) // true
// 量词:* - 0个或多个,相当于{0,}
var reg = /ab*c/;
console.log(reg.test('abbc')) // true
// 量词:? - 0个或1个,相当于{0,1}
var reg = /ab?c/;
console.log(reg.test('abc')) // true
//^ - 开头(检查一个字符串是否以a开头)
var reg = /^a/;
console.log(reg.test('abc')) // true
//$ - 结尾(检查一个字符串是否以a结尾)
var reg = /a$/;
console.log(reg.test('bba')) // true
/*
* 【检查一个字符串是否是一个合法的手机号】
* 第一位:以1 开头 ^1
* 第二位:3-9任意数字 [3-9]
* 三位及以后是9个任意数字 [0-9]{9}$
*/
var reg = /^1[3-9][0-9]{9}$/;
console.log(reg.test('13122666677')) // true
/*
* 【检查一个字符串是否含有.】
* . 表示任意字符
* 在正则表达式中使用\作为转义字符
* \. 表示 .
* \\ 表示 \
* 注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中的转义字符,
* 如果要使用\则需要使用\\来代替
*/
var reg = /\./;
console.log(reg.test('a.aa')) // true
/*
* \w - 表示任意字母、数字、下划线(_) 相当于:[A-z0-9]
* \W - 除了数字、字母、下划线(_) 相当于:[^A-z0-9]
* \d - 任意的数字 相当于:[0-9]
* \D - 除了数字 相当于:[^0-9]
* \s - 空格
* \S - 除了空格
* \b - 单词边界
* \B - 除了单词边界
*/
// 检查一个字符串中是否含有单词 'child'
var reg = /\bchild\b/;
console.log(reg.test('child')) // true
console.log(reg.test('children')) // false
// 去除字符串中的空格
console.log(' r e g '.replace(/\s/g,''))
// 去除字符串中的前后空格
console.log(' r e g '.replace(/^\s* | \s*$/g,''))
/*
* 邮箱格式
* suzy.cai@abc.com.cn
* suzy -> (任意字母、数字、下划线) —— \w{3,}
* .cai ->(点+任意字母、数字、下划线) -> (可选) —— (\.\w+)*
* @ -> @
* abc.com.cn -> 任意字母、数字 + 点 + 任意字母(2-5位) —— [A-z0-9]+(\.[A-z]{2,5}){1,2}
*/
// 去除字符串中的前后空格
var reg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/
console.log(reg.test('suzy.cai88@qq.com.cn'))
10、原型链继承
function Name() {
this.name = 'suzy'
}
function Age() {
this.age = 18
}
Age.prototype = new Name()
var p = new Age()
console.log(p.name) // suzy
console.log(p.age) //18
11、 ES5
1、es5 —— 严格模式
- 严格模式下,声明变量需要使用var 。
"use strict";
age = 18
console.log(age) // age is not defined
- 严格模式下,构造函数必须要用new 调用。
"use strict";
function SetAge(age) {
this.age = age; // Cannot set property 'age' of undefined
}
SetAge(11)
- 严格模式下, eval 有自己的作用域
// 用eval的时候如果不用严格模式 网站容易被攻击。
"use strict";
var age = 30;
eval('var age = 18;console.log(age)') // 18
console.log(age) // 30 (如果没有使用严格模式,此处返回:18)
2、es5 —— JSON对象
- JSON.stringify()
- JSON.parse()
3、es5 —— Object 扩展
- Object.create()
作用:
- 以指定对象为原型创建新的对象
- 为新的对象指定新的属性,并对属性进行描述
- value:指定值
- writable:是否可修改(默认是false)
- configurable:是否可以被删除(默认是false)
- enumerable:是否能用for in 枚举(默认是false)
// Object.create()
var obj = {
username: 'suzy',
age: 18
}
var obj1 = {}
obj1 = Object.create(obj, {
sex: {
value: '女',
writable: false, // 是否可修改
configurable: false, // 是否可删除
enumerable: true // 是否能用for in 枚举
}
})
console.log(obj1.username) // suzy
console.log(obj1.sex) // 女
// writable: false
obj1.sex = '男'
console.log(obj1.sex) // 女 (writable: false 时 不可修改,所以还是返回女)
// configurable: false
delete obj1.sex
console.log(obj1.sex) // 女 说明没有被删除.
// enumerable: true
for (var i in obj1) {
console.log(i) // sex username age(如果enumerable: false,只返回:username age)
}
- Object.defineProperties()
作用:
为指定对象定义扩展多个属性
- get :用来获取当前属性值的回调函数
- set :修改当前属性值的触发的回调函数,并且实参即为修改后的值
- 存取器属性:setter,getter 一个用来存值,一个用来取值
// Object.defineProperties
var obj2 = {
firstName: 'cai',
lastName: 'suzy'
}
Object.defineProperties(obj2, {
fullName: {
get: function() { // 获取扩展属性的值 (惰性求职:fullName 一开始是:...)
return this.firstName + ' ' + this.lastName
},
set: function(data) { // 监听扩展属性,当扩展属性发生变化的时候会自动调用.自动调用后会将变化的值注入到set 函数
console.log(data) // 'cai shuzhen'
var names = data.split(' ')
console.log(names) // ['cai','shuzhen']
// 设置新的值
this.firstName = names[0]
this.lastName = names[1]
}
}
})
// 此时会去执行 get 方法
console.log(obj2.fullName) // 'cai suzy'
// 此时会去执行 set 方法
obj2.fullName = 'cai shuzhen'
console.log(obj2.firstName) // "cai"
console.log(obj2.lastName) // "shuzhen"
console.log(obj2.fullName) // "cai shuzhen"
// 方法同上
var obj = {
firstName: 'cai',
lastName: 'suzy',
get fullName() {
return this.firstName + ' ' + this.lastName
},
set fullName(data) {
console.log(data) // 'cai shuzhen'
var names = data.split(' ')
console.log(names) // ['cai','shuzhen']
// 设置新的值
this.firstName = names[0]
this.lastName = names[1]
}
}
console.log(obj.fullName) // 'cai suzy'
obj.fullName = 'cai shuzhen'
console.log(obj.fullName) // 'cai shuzhen'
4、es5 —— Array 扩展
- Array.prototype.indexOf(value)
- Array.prototype.lastIndexOf(value)
- Array.prototype.forEach(function(item, index){})
- Array.prototype.map(function(item, index){})
- Array.prototype.filter(function(item, index){})
var arr = [2, 4, 3, 1, 2, 6, 5, 4]
// indexOf
console.log(arr.indexOf(4)) // 1 (输出第一个4 的下标)
// lastIndexOf
console.log(arr.lastIndexOf(4)) // 7 (输出最后一个4 的下标)
// forEach
arr.forEach(function(item, index) {
console.log(item, index) // 遍历数组 (返回每个的值和下标)
})
// map
var arr2 = arr.map(function(item, index) {
return item + 10
})
console.log(arr2) // [12, 14, 13, 11, 12, 16, 15, 14] (根据arr 产生一个新数组,要求每个元素都比原来大10)
// filter
var arr3 = arr.filter(function(item, index) {
return item > 3
})
console.log(arr3) // [4, 6, 5, 4] (根据arr 产生一个新数组,返回的每个元素要大于3)
5、es5 —— call apply bind 用法
call apply 是立即调用函数
bind 是将函数返回。(通常用于指定回调函数的this,因为它不会立即调用)
var obj = {
userName: 'suzy'
}
function foo(data, data2) {
console.log(this, data, data2)
}
foo.call(obj, 33, 11) // call 传参是第二个参数开始一次传递
foo.apply(obj, [33, 11]) // apply 传的是数组
foo.bind(obj, 33, 11)() // bind 不会立即调用