javascript的基础知识
js中的数据类型?
1、js的原始值
特别注意:首先原始类型存储的都是值,是没有函数可以调用的
- 1.number数字类型 数字类型,表示32位(4字节)的整数以及64位(8字节)的浮点数,所有的小数都占8字节
- 2.string 字符串类型 由Unicode字符,数字,标点组成
- 3.boolen 布尔类型
仅有两个值:true 和 false boolean 与 number 再将进行运算时,true当做1; false当做0;
- 4.null 类型
让对象不再指向任何空间
如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null - 5.undefined 未定义
出现场合 1.声明变量但未赋值 2.试图访问对象中不存在的属性
- 6.symbol是由ES6规范引入的一项新特性,它的功能类似于一种标识唯一性的ID
2、对象类型
object(对象)
混淆点: 对象类型和原始类型的不同之处?
在 JS 中,除了原始类型那么其他的都是对象类型了。对象类型和原始类型不同的是,原始类型存储的是值,对象类型存储的是地址(指针)。当你创建了一个对象类型的时候,计算机会在内存中帮我们开辟一个空间来存放值,但是我们需要找到这个空间,这个空间会拥有一个地址(指针)
let str='字符'
let strRe=str+'2'
let obj=[]
let objRe=obj
objRe.push(2)
console.log(objRe); //[2]
console.log(obj); //[2]
console.log(str); //字符
console.log(strRe); //字符2
从上面的案例 我们可以看到在使用对象obj进行复制后得到的objRe,但是在值改变objRe的值后 原来的obj也发生了变化,但是字符串中的复制却没发生变化,这里产生不同结果的原因是,复制对象我们获取的是对象的地址,js会把当前地址的值显示在objRe上,但是我们如果改变此值的话,肯定是对当前地址进行操作,所以obj和objRe的数据会相同,因为他们都是显示同一个地址的值。
如何正确判断类型
1 使用typeof
作用:typeof对于原始类型来说,除了null都可以显示正确的类型
//typeof的使用
console.log(typeof 1) //number
console.log(typeof '1')//string
console.log(typeof true)//boolean
console.log(typeof undefined)//undefined
console.log(typeof Symbol())//symbol
console.log(typeof null)//object
console.log(typeof ['1','2'])//object
console.log(typeof {})//object
//typeof对于对象来说,除了函数都会显示object,所以说typeof并不能准确判断变量到底是什么类型
//如果我们想判断一个对象的正确类型,这时候可以考虑使用instanceof,因为内部机制是通过原型链来判断的。
类型的转换
1、隐式转换
在某些操作中,变量的数据类型会自动的产生转换操作
- 1.数字 + 字符串 : 数字转换为字符串
- 数字 + 布尔值 : 将布尔值转换为数字
- 字符串+ 布尔值: 将布尔值转换为字符串
- 布尔值+布尔值: 将布尔值转换为数字
隐性类型转换步骤
1、首先看双等号前后有没有NaN,如果存在NaN,一律返回false。
2、再看双等号前后有没有布尔,有布尔就将布尔转换为数字。(false是0,true是1)
3、接着看双等号前后有没有字符串, 有三种情况:
- 1、对方是对象,对象使用toString()或者valueOf()进行转换;
- 2、对方是数字,字符串转数字;
- 3、对方是字符串,直接比较;
- 4、其他返回false
4、如果是数字,对方是对象,对象取valueOf()或者toString()进行比较, 其他一律返回false
// 调用规则:
1. 如果我们没有重新定义valueOf和toString,其隐式转换会调用默认的toString()方法,
将函数本身内容作为字符串返回;
2. 如果我们自己重新定义toString/valueOf方法,那么其转换会按照我们的定义来,
其中valueOf比toString优先级更高 尝试把对象转成简单数据类型,
3. 如果没有得到简单数据类型,再继续去调用toString方法
4. 看到+时,和上面的结论一样,但是alert , [x].join(“”)等这类特殊的表达,均调用toString()
5、null, undefined不会进行类型转换, 但它们俩相等
2、强制转换
1、toString()
作用:将指定类型的数据转换为"字符串" 1.Number 类型的 toString() 它有两种模式,即默认模式和基模式。
- 1 默认模式时当前进行转换的数字会被装换为十进制
let iNum1 = 20;
let iNum2 = 21.0
let iNum3 = 21.3;
alert(iNum1.toString()); //20
alert(iNum2.toString()); //21
alert(iNum3.toString()); //21.3
- 2基模式时当前的Number会根据填写的类型进行装换
let num=21
alert(num.toString(2));//10101
alert(num.toString(8));//25
alert(num.toString(16));//15
2.arr数组类型的toString()
let arr=[12,45,78,101]
let arr2Name=['第一位客户','第二位客户','第三位客户'];
console.log(arr.toString());//12,45,78,101
console.log(arr2Name.toString());//第一位客户,第二位客户,第三位客户
数组类型使用toString() 可以使数组的值可以用逗号分隔起来。
- 3.Boolean 类型的toString()
let bool=true
console.log(bool.toString());//true
-
- null 和 undefiend 没有toString()方法
2、parseInt()
作用:能解析任意类型的数据,并返回整数
语法:parseInt(string, radix)
参数1:必填 参数2: 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间
let num=12
let num2=12.56
let str='这是字符12'
let str2="123数字"
let null1=null
let undef=undefined
let obj={
id:12,
name:'obj'
}
console.log(parseInt(num)); //12
console.log(parseInt(num,8)); //10
console.log(parseInt(num2)); //12
console.log(parseInt(str)); //NaN
console.log(typeof parseInt(str)); //number
console.log(parseInt(str2)); //123
console.log(parseInt(obj)); //NaN
console.log(parseInt(null1)); //NaN
console.log(parseInt(undefined)); //NaN
3、parseFloat()
作用:能解析任意类型的数据,并返回一个浮点数数
语法:parseFloat(string)
let float=13.658
console.log(parseFloat(float)); //13.658
4、Number()
作用:将任意类型的数据转换为number类型,若包换非法字符结果就是NaN
var test1= new Boolean(true);
var test2= new Boolean(false);
var test3= new Date();
var test4= new String("999");
var test5= new String("999 888");
document.write(Number(test1)); //1
document.write(Number(test2)); //0
document.write(Number(test3)); //1569389275934
document.write(Number(test4)); //999
document.write(Number(test5)); //NaN
注意点:如果参数是 Date 对象,Number() 返回从 1970 年 1 月 1 日至今的毫秒数。
5、Math的方法
作用:把Math当做对象接可以调用它的所有属性和方法。
| 方法 | 作用 | 例子 |
|---|---|---|
| abs(x) | 返回数的绝对值。 | Math.abs(-4.5) 4.5 |
| ceil(x) | 对数进行上舍入 | Math.ceil(4.5) 5 |
| floor(x) | 对数进行下舍入 | Math.floor(4.5) 4 |
| random() | 返回介于 0 ~ 1 之间的一个随机数。 | Math.random() 0.0 ~ 1.0 之间的一个伪随机数。 |
| round(x) | 把数四舍五入为最接近的整数 | Math.round(4.5) 5 Math.round(4.2) 4 |
3、常用的运算方法
- 1 isNaN()
用途:用于检查其参数是否是非数字值,也于检测 parseFloat() 和 parseInt() 的结果,以判断它们表示的是否是合法的数字。当然也可以用 isNaN() 函数来检测算数错误,比如用 0 作除数的情况。
let num=10
let string='这是一段字符串'
console.log(isNaN(num));//false
console.log(isNaN(string));//true
- 2 Date()
用途:Date()构造函数,用来创建表示日期和时间的对象。
var then = new Date(2011,0,1) // 2011年1月1日
var later = new Date(2011,0,1,17,10,30) // 2011年1月1日 17:10:30
var now = new Date() //当前的日期和时间
var elapsed = now-then // 日期减法:计算时间间隔的毫秒数。
later.getFullYear() //2011
later.getMonth() // 0,从0开始计数的月份
later.getDate() // 1,从1开始计数的天数
later.getHours() //当地时间 17:5
later.getUTCHours() 使用UTC表示小时的事件,基于时区。
- 3 == 与 === 的区别 相同点:
都是用于比较两个值是否相等
不同点
"==="也称为严格相等运算符(有时也称作恒等运算符),它用来检测两个操作数是否严格相等. '===' 首先计算其操作数的值,然后比较这两个值,比较过程没有任何类型转换
"=="称作相等运算符,它用来检测两个操作上是否相等,这里的‘相等’的定义非常宽松,可以允许进行类型转换 在比较不同类型的数据时,相等运算符会先将数据进行类型转换,然后再用严格相等运算符比较。
(1)不同类型值 如果两个值的类型不同,直接返回false。
(2)同一类的原始类型值 同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false。
(3)同一类的复合类型值 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象。
(4)undefined和null undefined 和 null 与自身严格相等。
- 4 delete运算符
用途:是一元操作符,它是用来删除对象属性或者数组元素的
1.能删除一个对象的属性:
var x = { a: 1 };
delete x.a; // true
x.a; // undefined
2.不能删除用var语句声明的变量
3.不能删除一个函数和函数参数
4.不能删除一些内置核心和客户端属性
5.deletex希望它的操作数是一个左值,如果不是左值,那么delete将不进行任何操作同时返回true
进行类型转换(加减乘除)详解
链接查看:www.haorooms.com/post/js_czf…
语句
break语句
作用:break 语句用于退出 switch 语句或循环语句(for, for ... in, while, do ... while)。
当 break 语句用于 switch 语句中时,会跳出 switch 代码块,终止执行代码。
当 break 语句用于循环语句时,会终止执行循环,并执行循环后代码(如果有的话)。
break 语句同样可用于可选的标签引用,用于跳出代码块。
continue语句
作用:continue 用于跳过循环中的一个迭代,并继续执行循环中的下一个迭代。
continue 与break语句的区别是, break 是结束整个循环体,continue是结束单次循环。
但是,在执行 continue 语句时,表现出了两种不同类型的循环:。
在while循环中,会先判断条件,如果条件为 true,循环再执行一次。。
在for循环中,自增长表达式 (如:i++) 会先计算,然后再判断条件是否为true,再决定是否执行迭代。
return语句
作用:是让解释器跳出函数体的执行,并提供本次调用的返回值
只能在函数体内出现,如果不是的话会报语法错误
throw语句
作用:throw语句用来抛出一个用户自定义的异常。当前函数的执行将被停止(throw之后的语句将不会执行),并且控制将被传递到调用堆栈中的第一个catch块。如果调用者函数中没有catch块,程序将会终止。
function getRectArea(width, height) {
if (isNaN(width) || isNaN(height)) {
throw "Parameter is not a number!";
}
}
try {
getRectArea(3, 'A');
}
catch(e) {
console.error(e);
// expected output: "Parameter is not a number!"
}
try/catch/finally语句
try {
// 通常来讲,这里的代码会从头执行到结尾而不会产生任何问题,
// 但有时会抛出一个异常,要么是由throw语句显示抛出
// 要不是通过调用一个方法间接抛出异常
} catch (e) {
// 当且仅当try语句块抛出了异常,才会执行这里的代码
// 这里可以通过局部变量e来获取对Error对象或者抛出的其他值的引用
// 这里的代码块可以基于某种原因处理这个异常,也可以忽略这个异常
// 还可以通过throw语句重新抛出异常
} finally {
// 不管try语句是否抛出了异常,这里的逻辑总是会执行,终止try语句块的方式有:
// 1)正常终止,执行完语句块的最有一条语句
// 2)通过break ,continue 或者return 语句终止
// 3)抛出一个异常,异常被catch从句捕获
// 4)抛出一个异常,异常未被捕获,继续向上传播
}
<div id="message">
</div>
<div id="demo"></div>
<script>
function myFunction() {
var message, x;
message = document.getElementById("message");
message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if (x == "") throw "为空";
if (isNaN(x)) throw "不是一个数字";
if (x > 10) throw "太大";
if (x < 5) throw "太小";
}
catch (err) {
message.innerHTML = "输入的值 " + err;
}
finally {
document.getElementById("demo").value = "";
}
}
console.log(myFunction()) //输入的值 不是一个数字
</script>
数组
什么是数组
:即一组数据,使用一个变量来存放多个数据
如何声明一个数组
1、声明一个空数组变量;
var 数组名 = [ ];
2、声明数组并赋初始值;
var 数组名 = [数据1,数据2,数据3...... ];
3、声明一个空数组变量;
var 数组名 = new Array();
var a = new Array(10);//调用时有一个数值参数,它指定长度
4、声明一个数组并赋初始值
var 数组名 = new Array(数据1,数据2,数据3......);
数据的特点
- JavaScript数组是无类型的
数组元素可以是任意类型:并且同一个数组中的不同元素也可能有不用的类型。数组的元素甚至也可能是对象或其他数组,这允许创建复杂的数据结构,如对象的数组和数组的数组。 - 数组的索引是基于零的32位数值:
第一个元素的索引为0,最大可能的索引为4294967294(2∧32-2),数组最大能容纳4294967294个元素, 所有的索引都是属性名,但只有在0~2^32-2之间的整数属性名才是索引。。 - JavaScript数组是动态的:
- 数组元素的索引不一定要连续的,他们之间可以有空缺
- 当使用负数和非整数来索引数组
这种情况下,数值转换为字符串,字符串作为属性名来用。既然名字不是非负整数,它就只能当做常规的对象属性,而非数组的索引。同样,如果凑巧使用了是非负整数的字符串,它就当做数组索引,而非对象属性。当使用的一个浮点数和一个整数相等时情况也是一样的:
let arr=[]
arr[-1.2]=1.2
arr["3"]="this is three"
arr[2.3]=2.3
console.log(arr) ;//[empty × 3, "this is three", -1.2: 1.2, 2.3: 2.3]
console.log(arr[3]) ;//this is three
console.log(arr[2]);//undefined
console.log(arr[1]);//undefined
console.log(arr.length) ;//4
console.log(arr[-1.2]) ;//1.2
//删除操作
arr.length = 0;//删除所有的元素,arr为{}
delete arr[3]; //arr删除第三个元素
shift()方法,从数组头部删除一个元素。
当使用for/in循环时,a1和a2之间的区别也很明显
需要注意的是,当省略数组直接量中的赋值(使用连续的逗号,比如[1,,3]),
这时所得到的数组也是稀疏数组,省略掉的值是不存在的:
var a1 = [,];//子数组没有元素,长度为1
var a2 = [undefined];//次数在包含一个值的undefined的元素
console.log(0 in a1);// false:a1在索引0处没有元素
console.log(0 in a2);//true:a2在索引0处有一个值为undefined元素
数组的常用方法
- join()
作用:将数组中的元素通过指定的分隔符连接到一起,并返回连接后的字符串 写法:arr.join(参数) //参数不填时默认直接连接(不改变数组)
let arr=[2,3,4,5]
console.log(arr.join("")) //2345
console.log(arr.join(",")) //2,3,4,5
- concat()
作用:会合并之前的值并创建一个新的数组。Array.concat(参数1,参数2,...)(不改变数组)
1.concat不会改变现有数组,而是返回拼接后的
2.每个参数不一定非是数组,也可以是普通的数据。
let arr=[2,3,4,5]
let arr1=[6,7,8]
console.log(arr.concat(arr1) ) //[2, 3, 4, 5, 6, 7, 8]
console.log(arr.concat(arr1,'concat')) //[2, 3, 4, 5, 6, 7, 8, "concat"]
console.log(arr.concat(arr1,{'name':'xin','age':14})) //[2, 3, 4, 5, 6, 7, 8, {…}]
console.log(arr) //[2, 3, 4, 5]
console.log(arr.concat(4,[5,[6,7]]))
//(7) [2, 3, 4, 5, 4, 5, Array(2)]
// 0: 2
// 1: 3
// 2: 4
// 3: 5
// 4: 4
// 5: 5
// 6: Array(2)
// 0: 6
// 1: 7
- slice()
作用:Array.slice(参数1,参数2)方法返回指定数组的一个片段或子数组。它的两个参数分别指定了片段的开始和结束的位置。返回的数组包含第一个参数指定的位置和所有到但不含第二个参数指定的位置之间的所有数组元素。如果只指定一个参数,返回的数组将包含从开始位置带数组结尾的所有元素。如参数中出现负数,他表示相对于数组中最后一个元素的位置。例如,参数-1指定了最后一个元素,而-3指定了倒数第三个元素。
slice()不会改变调用的数组
let arr=[2,3,4,5,6,7,8]
console.log(arr.slice(-1)) //[8]
console.log(arr.slice(0,arr.length)) //[2,3,4,5,6,7,8]
console.log(arr.slice(3,6)) // [5, 6, 7]
console.log(arr) //[2,3,4,5,6,7,8]
- splice()
作用:删除指定位置,并替换,返回删除的数据
用法:arr.splice.(index,number,item1,item2...) 在插入或删除点之外的数组元素会根据需要增加或减少他们的索引值,因此数组的其他部分仍然保持连续的。splice()的第一个参数指定了插入和(或)删除的起始位置。第二个参数指定了应该从数组中删除的元素的个数。如果省略第二个参数,从起始点开始到数组结尾的所有元素都将被删除。第三个参数是增加的元素。splice()返回一个由删除元素组成的数组,或者没有删除元素就返回一个空数组(会改变调用的数组)
let arr=[2,3,4,5,6,7,8]
console.log(arr.splice(3,1)) ;//[5]
console.log(arr.splice(0,1)) //[2]
console.log(arr) //[3, 4, 6, 7, 8]
- reverse()
作用:对字符串数组进行翻转
用法:arr.reverse()
let s=["h", "e", "l", "l", "o"]
s.reverse()//["o", "l", "l", "e", "h"]
ES5 中的数组方法
- forEach()
作用:对原数组中每个元素执行相同操作
用法:arr.forEach(function(value,index,arr){})参数为回调函数,会遍历数组所有的项,回调函数接受三个参数,分别为value,index,arr;forEach没有返回值
var arr=[1,2,3,4,5];
//将原数组中每个数*2
arr.forEach(function(elem,i,arr){
arr[i]=elem*2;
});
console.log(arr) //2,4,6,8,10
注意,forEach()无法在所有元素都传递给调用的函数之前终止遍历。也就是说,没有像for循环中使用的相应的break语句。如果要提前终止,必须把forEach()方法放在一个try块中,并能抛出一个异常。如果forEach()调用的函数抛出foreach.break异常,循环会提前终止。
var arr=[1,2,3,4,5];
//将原数组中每个数*2
try{
arr.forEach(function(elem,i,arr){
arr[i]=elem*2;
//停止循环的条件
if(elem==4){
throw Error()
}
});
}catch(e){
console.log("进入此错误?")
}
console.log(arr);//2,4,6,8,5
- map()
作用:依次去除原数组中每个元素,执行相同操作后,放入新数组中返回
用法:1.同forEach功能;2.map的回调函数会将执行结果返回,最后map将所有回调函数的返回值组成新数组返回。
var arr=[1,2,3,4,5];
var evens=arr.map(function(elem){
return elem*2;
});
console.log(evens) //2,4,6,8,10
- every()
作用:判断数组中是否所有元素都符合要求,只有所有元素都符合,才返回true
用法:arr.every(function(value,index,arr){});
var bool=arr.every(function(elem,I,arr){
//elem 自动获得当前元素值
//I 自动获得当前位置
//arr 自动获得当前数组=>this
return 针对当前元素
})
- some()
作用:判断数组中是否包含符合要求的元素,只要有一个就返回true 用法:同every() - filter()
作用:选取出原数组中符合条件的元素,组成新数组返回
var arr=[1,2,3,4,5];
var evens=arr.filter(function(elem){
return elem%2==0;
})
console.log(arr);//[1,2,3,4,5]
console.log(evens);//[2,4]
- reduce()
作用:将数组中每个元素统计汇总出一个最终的结果
用法:reduce()需要两个参数。第一个是执行化简操作的函数。化简函数的任务就是用某种方法把两个值组合或化简为一个值,并返回化简后的值。在上述例子中,函数通过加法、乘法或取最大值的方法组合两个值。第二个(可选)的参数是一个传递给函数的初始值。
var result=arr.reduce(function(elem,I,arr){
//prev:截止目前的临时汇总值
return prev+elem;
},base)
以base值为基数,累加arr中每个元素值
let class2=[1,3,5,2,1];
let sum=10
sum=class2.reduce(function(prev,elem){
return prev+elem
},sum);
console.log(sum)//22
ES6 中的数组方法
- new Set()
作用:Set对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的。(去重)
用法:new Set()可以放置数组,从而给该数组去重,它拥有属性 size 来判断当前对象值的个数。 也可以创建一个实例,它拥有方法
实例方法:
1、Set.add(value)
作用:在Set对象尾部添加一个元素。返回该Set对象。
2、Set.clear()
移除Set对象内的所有元素。
3、Set.delete(value)
移除Set的中与这个值相等的元素,返回Set.prototype.has(value)在这个操作前会返回的值(即如果该元素存在,返回true,否则返回false)。Set.prototype.has(value)在此后会返回false。
4、Set.entries()
返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值的[value, value]数组。为了使这个方法和Map对象保持相似, 每个值的键和值相等。
5、Set.forEach(callbackFn[, thisArg])
按照插入顺序,为Set对象中的每一个值调用一次callBackFn。如果提供了thisArg参数,回调中的this会是这个参数。
6、Set.has(value)
返回一个布尔值,表示该值在Set中存在与否。
7、Set.prototype.values()
返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值。
//创建一个set实例
let set = new Set()
set.add('name')
set.add('age')
set.add('sex')
console.log(set.has('name')) //删除操作前
set.delete('name')
let setArr = set.entries()
//获取值
function getSetValue(value1, value2, set) {
console.log('value: ' + value1 + '/' + value2)
}
console.log(set)
console.log(set.has('name')) //删除操作后
console.log(setArr)
console.log(set.forEach(getSetValue))
//value: age/age
// value: sex/sex
console.log(set.values()) //{"age", "sex"}
console.log(set.values().next().value) //age
js的重点部分一(ES5)
严格模式
作用:在开发项目的时候能已更严格的语法进行开发。
如何使用:
- 1、在整个js文件或script标签内启用严格模式 在js文件或script标签内第一行:“use strict”; 何时启用:新项目,都要启用
- 2、仅在单个函数内启用严格模式:
在函数内的第一行:“use strict”;
何时:旧项目改造时,要逐个功能向严格模式迁移
限制的地方:
- 1、禁止给未声明的变量赋值;
- 2、将静默失败升级为错误: 静默失败:既修改不成功,又不报错!
- 3、不建议使用arguments,arguments.callee
- 4、普通函数调用和匿名函数自调中的this不再指向window!而是undefined
对对象的严格保护
作用:对js中偶同的对象对自己的属性和结构,进行验证和保护的方法。
如何使用
1 保护属性:
ES5规定:对象的属性分为两大类:
1 命名属性:可用点直接访问到的属性+(此处分为两类)
- 1 数据属性:直接存储属性值的属性:
查看一个属性的四大啊特性:Object.getOwnPropertyDesciptor(obj,"属性名")
返回值:{ value:实际存储属性值;
writable:true/false,控制只读
enumerable:true/false,控制能否被for in遍历到 但是用点依然可以访问到
configurable:true/flase,控制: 1、控制能都删除该属性; 2、控制能否修改其他特性; 一旦改为false,不可逆! 总是伴随其他特性的修改,充当双保险 }
如何修改四大特性保护数据属性:
Object.defineProperty(obj,“属性名”,{
要修改的特性:值,
…:…
})
问题:一次 只能修改一个属性的四大特性
解决:同时修改多个
Object.defineProperty(obj,“属性名”,{
属性名:{
四大特性:值,
…:…
属性名:{
四大特性:值,
…:…
… …
}
});
说明:如果要修改的属性不存在,则自动创建,但是,自动创建的属性,四大特性默认值都是false
问题:只能用固定的三种特性保护属性,无法用自定义规则来灵活地保护属性;
- 2 访问器属性:
1、概念:不直接存储属性值,仅提供对其他数据属性的保护
2、何时:只要用自定义规则保护属性时
3、如何:2步:
1、定义隐藏的数据属性,起别名;实际存储数据
问题:使用enmuerable隐藏的属性,防for in
,防不住点,别人可用eric._age绕过访问器属性,直接篡改受保护的属性 解决:使用
2、定义访问器属性,从受保护的数据属性中读取或修改数据
Object.definedProperties(eric,{
_age:{enumerable:false,configurable:false}
age:{//访问器属性
get(){return _age}
set(val){
if(val>=18&&val<=65)
_age=val;
else
throw new RangeError("年龄必须介于18~65之间");
},
enumerable:true,
configurable:true
} ,
})
如何使用:访问器属性的用法和普通属性完全一样
只不过:在试图获取属性值时,
2、内部属性:不能用点直接访问到的属性: class proto
2 防篡改(保护结构):
- 1、防扩展:禁止向对象中添加新属性
如何使用:Object.preventExtensions(obj)
原理:每个对象内都有一个隐藏的内部属性extensible,默认都是true
preventExtensions将extensible改为false - 2、密封:既 禁止扩展,又禁止删除!
如何密封:Object.seal(obj)
原理:既修改对象的extensible为false,又自动修改每个属性的configurable为false
3、Object.create()
- 1、概念:仅基于一个现有父对象,创建他的子对象,并为子对象扩展新的自有属性
- 2、何时:今后,如果仅基于父对象,也想创建子对象时
var child=Object.create(father,{//Object.defineProperties
属性名:{四大特性}
… : …
});
//例如
var father={ bal:1000000000, car:"infiniti"};
var hmm=Object.create(father,{
//defineProperties
phone:{
value:"iPhone8",
writable:true,
enumerable:true,
configurable:true
},
bao:{
value:"LV",
writable:true,
enumerable:true,
configurable:true
}
});
4、call/apply/bind:
相同:如果函数中的this不是想要的,都可替换
不同:
call/apply:强行*调用*一个函数,并*临时*替换函数中的this为指定对象
call:要求传入函数的参数必须单独传入
apply:要求传入函数的参数必须放在数组中整体传入
apply可先打散数组参数为单个元素,再传入
bind:基于一个现有函数*创建*一个相同的新函数,并*永久*绑定this为指定对象
总结:如果是临时*调用*一个函数,用call/apply
如果创建一个新函数永久绑定this时
所有回调函数中的this,要想替换都用bind
因为回调函数不是立刻执行且不止执行一次!
function calc(base,bonus1,bonus2){
document.write(this.ename+"的总工资:"+(
base+bonus1+bonus2
)+"<br>");
}
var lilei={ename:"Li Lei"};
var hmm={ename:"Han Meimei"};
//lilei和hmm共用同一个计算器
//lilei临时借用
calc.call(lilei,10000,2000,3000);
var sals=[4000,7000,6000];
//hmm临时借用
calc.apply(hmm,sals);
//calc( 4000,7000,6000)
//lilei创建了一个自己专属的lilei_calc
//功能和calc一样
//提前永久绑定了this->lilei
//提前永久绑定了第一个参数base为10000
var lilei_calc=calc.bind(lilei,10000);
//lilei_calc:function calc(base=10000,...){
//this->lilei
//}
//lilei用自己专属的calc,不用再重复输入
lilei_calc(2000,3000);
//hmm想临时借用,但借不了
lilei_calc.call(hmm,4000,7000,6000);
js的重点部分二(ES6)
1、块作用域
1、let:声明一个不会被提前的变量
- 1、为什么使用let:传统JS中声明提前破坏了程序正常的执行顺序
- 2、何时:所有的var,都要用let代替
- 3、原理:let a之前不允许提前使用a,也不允许重复声明a
2、let为js添加了块级作用域
- 1、块级作用域概念:代码中任何一对()之间的语句称为一个代码块,代码块中的变量只能在块内使用
- 2、原理:自动使用匿名函数自调方式,来包裹内层函数
2、箭头函数:
1、作用:简化回调函数
2、使用:
1、去function加=>
2、更简化:如果只有一个参数,可以省略()
3、更简化:如果回调函数中只有一句话可省略{},
强调:如果只有一句话,结尾的;要去掉
4、更简化:如果仅有一句return,可以继续省略return
3、特点:箭头内外共用一个this
3、参数增强:三种情况
1、默认值default:
概念:在ES6中可对参数指定默认值,调用时,如果没有传入参数值,则默认使用提前指定的默认值
Array.prototype.indexOf=function(elem,fromi=0){
//fromi=fromi||0
}
强调:由默认值的参数,必须放在参数列表的最后
2、剩余参数(rest):
- 作用:当传入函数的参数个数不确定时,可用…借助剩余的一切参数
- 为什么:arguments的2大问题
1、总是获得全部参数,不能有选择的获得部分
2、是类数组对象,不是纯正的数组,不能使用数组API
3、不能改名
3、散播(spread):
- 作用:在函数调用时,用...打散数组类型的参数为单个元素,再传入函数——代替apply
- 用法:在调用时,传入参数时用"...数组"打散数组参数,单个元素分别传入
4、模板字符串
- 作用:支持内置表达式的字符串拼接——简化了字符串拼接
- 用法:
- 模板字符串必须用``包裹
- 如果包含需要动态计算的表达式,则用${}包裹
- 反引号内默认支持换行
- 模板字符串必须用``包裹
5、解构
- 作用:将一个对象或者数组中的成员分别赋值给多个单独的变量——简化批量赋值,数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
- 用法:
1、数组解构:
var arr=[1,2,3];
var[a,b,c]=arr;
console.log(a,b,c); => 1 2 3
强调:数组解构靠下标对应
2、对象解构:
var date={y:2017,m:9,d:21};
var {y:year,m:month,d:date}=date;
console.log(year,month,date);
强调:对象解构靠属性名对应
3、函数调用时解构:
定义函数时:function fun(y:year,m:month,d:date){…}
调用时: var date={ y:2017,m:9,d:21};
fun();
6、class:类型
- 作用:封装一类对象统一结构和API的程序结构——简化JS中的面向对象
- 用法:
1、用class 类型名{}包裹之前的构造函数和原型对象方法
2、构造函数名升级为class 名,构造函数更名为constructor关键词
3、原型对象方法不用写类型.prototype和function直接写在class中的函数,自动添加到prototype中
简化继承:
1、class 子类型 extends 父类型
类似于:
Object.setPrototypeOf(
子类型.prototype,父类型.prototype);
2、借用父类型构造函数:super(参数)
不用call,不用this
其中:super特指父类型构造函数,且自动用当前正确this替换父类型构造函数中的this
super. 父类型原型方法(…)
例子如下:
class Flyer{
constructor(fname,speed){
this.fname=fname;
this.speed=speed;
}
fly(){//Flyer.prototype.fly
console.log(
this.fname+"以时速"+this.speed+"飞行");
}
toString(){
console.log("调用爷爷的toString");
return `fname:${this.fname},speed:${this.speed}`;
}
}
class Plane extends Flyer{
constructor(fname,speed,score){
super(fname,speed);
this.score=score;
}
getScore(){
console.log(
"击落"+this.fname+"得"+this.score+"分");
}
toString(){
console.log("调用爸爸的toString");
return super.toString()+`,score:${this.score}`;
}
}
var f16=new Plane("F16",1000,10);
- 静态方法:
1、概念:不需要实例化对象,就可直接访问的 成员
2、何时:只要一个方法,不需要实例化也能使用时
3、如何:static 方法(){…}
4、原理:相当于直接定义在构造函数对象上的方法 - 访问器属性:
get 属性名(){return this._属性名;}
set 属性名(val){
if(判断)
this
}
7、for of:简化版的for循环
- 作用: 代替for循环,遍历下标为数字的数组或类数组对象,这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。
不能遍历关联数组和对象,因为下标不是数字
1、无法获得下标——要用下标时,不能用for of
2、只能遍历所有,不能有选择的遍历
3、只能从前向后
8、promise
- 作用:回调函数的一种更直观的写法——规范回调函数的使用
- 用法:
1、前一个函数定义中:用一个巨大的Promise对象包裹函数的内容,并将Promise对象返回
2、promise有两个参数return new Promise(function(resolve,reject){}),参数一表示正确情况下(下个函数.then 的执行内容),参数二表示错误情况下(下个函数.catch下的执行内容)
return new Promise(function(resolve,reject)){
正常逻辑中:如果正常执行,调用resolve
如果出错,调用reject("错误信息"/"错误对象")
})
- 等待多个任务完成才执行
- 用法:Promise.all([函数1(),函数2(),…]).then(end)
map和set的区别
说明:两者搜可用来去重。 链接:www.liaoxuefeng.com/wiki/102291…
对象
对象的使用
var obj = {a: 1}
undefined
obj.a //方式一
1
obj["a"] //方式二
1
var b = 'a'
obj[b] //方式三
1
正则
正则表达式规则
- 简单的转义字符
| 表达式 | 可匹配 |
|---|---|
| \r, \n | 代表回车和换行符 |
| \t | 制表符 |
| / | 代表 "/" 本身 |
| ^ | 匹配 ^ 符号本身 |
| $ | 匹配 $ 符号本身 |
| . | 匹配小数点(.)本身 |
- 能够与 '多种字符' 匹配的表达式
| 表达式 | 可匹配 |
|---|---|
| \d | 任意一个数字,0~9 中的任意一个 |
| \w | 任意一个字母或数字或下划线,也就是 A |
| \s | 包括空格、制表符、换页符等空白字符的其中任意一个 |
| . | 小数点可以匹配除了换行符(/n)以外的任意一个字符 |
查看详细链接:www.haorooms.com/post/js_reg…
js线程
查看链接:www.haorooms.com/post/js_xia…
js的事件
双指操作事件
document.addEventListener('touchmove', function (event) {
if (event.touches && event.touches.length == 2) {
console.log('双指在移动');
event.preventDefault();
}
}, { passive: false });
构造函数
优缺点
缺点:存在浪费内存的问题
实例成员和静态成员的内容
- 1 实例成员就是构造函数内部通过this添加的成员 //实例成员只能通过实例化的对象来访问
- 2 静态成员 在构造函数本身上添加的成员 //静态成员只能通过构造函数来访问
function Star(uname,age){
this.uname=unama;
this.age=age
}
var wyr=new Star('吴颖柔',20)
console.log(wyr.uname) //这个是实例成员
Star.sex='女';//这个就是静态成员