JS总结
这里写目录标题
一级目录
二级目录
三级目录
数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
这里重点讲一下大家陌生的Symbol类型
Symbol 本质上是一种唯一标识符,可用作对象的唯一属性名,这样其他人就不会改写或覆盖你设置的属性值。
声明方法:
let id = Symbol("id“);
Symbol 数据类型的特点是唯一性,即使是用同一个变量生成的值也不相等。
let id1 = Symbol('id');
let id2 = Symbol('id');
console.log(id1 == id2); //false
Symbol 数据类型的另一特点是隐藏性,for···in,object.keys() 不能访问
let id = Symbol("id");
let obj = {
[id]:'symbol'
};
for(let option in obj){
console.log(obj[option]); //空
}
但是也有能够访问的方法:Object.getOwnPropertySymbols
Object.getOwnPropertySymbols 方法会返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
let id = Symbol("id");
let obj = {
[id]:'symbol'
};
let array = Object.getOwnPropertySymbols(obj);
console.log(array); //[Symbol(id)]
console.log(obj[array[0]]); //'symbol'
虽然这样保证了Symbol的唯一性,但我们不排除希望能够多次使用同一个symbol值的情况。
为此,官方提供了全局注册并登记的方法:Symbol.for()
let name1 = Symbol.for('name'); //检测到未创建后新建
let name2 = Symbol.for('name'); //检测到已创建后返回
console.log(name1 === name2); // true
通过这种方法就可以通过参数值获取到全局的symbol对象了,反之,能不能通过symbol对象获取到参数值呢?
是可以的 ,通过Symbol.keyFor()
let name1 = Symbol.for('name');
let name2 = Symbol.for('name');
console.log(Symbol.keyFor(name1)); // 'name'
console.log(Symbol.keyFor(name2)); // 'name'
最后,提醒大家一点,在创建symbol类型数据 时的参数只是作为标识使用,所以 Symbol() 也是可以的。
下面是数据类型里一些需要的方法
typeof 操作符
你可以使用 typeof 操作符来查看 JavaScript 变量的数据类型。
typeof "John" // 返回 string
typeof 3.14 // 返回 number
typeof NaN // 返回 number
typeof false // 返回 boolean
typeof [1,2,3,4] // 返回 object
typeof {name:'John', age:34} // 返回 object
typeof new Date() // 返回 object
typeof function () {} // 返回 function
typeof myCar // 返回 undefined (如果 myCar 没有声明)
typeof null // 返回 object
注意:
NaN 的数据类型是 number
数组(Array)的数据类型是 object
日期(Date)的数据类型为 object
null 的数据类型是 object
未定义变量的数据类型为 undefined
如果对象是 JavaScript Array 或 JavaScript Date ,我们就无法通过 typeof 来判断他们的类型,因为都是 返回 object。
constructor 属性
constructor 属性返回所有 JavaScript 变量的构造函数。
"John".constructor // 返回函数 String() { [native code] }
(3.14).constructor // 返回函数 Number() { [native code] }
false.constructor // 返回函数 Boolean() { [native code] }
[1,2,3,4].constructor // 返回函数 Array() { [native code] }
{name:'John', age:34}.constructor // 返回函数 Object() { [native code] }
new Date().constructor // 返回函数 Date() { [native code] }
function () {}.constructor // 返回函数 Function(){ [native code] }
将数字转换为字符串
全局方法 String() 可以将数字转换为字符串。
该方法可用于任何类型的数字,字母,变量,表达式:
String(x) // 将变量 x 转换为字符串并返回
Number 方法 toString() 也是有同样的效果。
(123).toString()
其他类型转化为布尔类型
Boolean(x)或者(!!x)
将字符串转换为数字
全局方法 Number() 可以将字符串转换为数字。
字符串包含数字(如 “3.14”) 转换为数字 (如 3.14).
空字符串转换为 0。
其他的字符串会转换为 NaN (不是个数字)。
方法 | 描述 |
---|---|
parseFloat() | 解析一个字符串,并返回一个浮点数。 |
parseInt() | 解析一个字符串,并返回一个整数。 |
自动类型转换
比如任何类型+" "最后得到的都是字符串
其他类型(-/*)0最后得到的是数字类型
JS中八进制前面加0,十六进制前面加0X
数字类型的最大值最小值分别是
Number.MAX_VALUE
Number.MIN_VALUE
Infinity代表无穷大-Infinity代表无穷小
NaN代表非数值
API
API(Application Programming Interface,应用程序编程接口)
任何开发语言都有自己的API
API的特征输入和输出(I/O)
API的使用方法(console.log())
函数和变量
函数的优先级高于变量的优先级
foo(); //输出的答案为1因为函数的优先级大于变量的优先级
var foo;
function foo() {
console.log(1);
}
foo = function() {
console.log(2);
}
构造函数
构造函数的函数名首字母必须大写,调用的时候必须用new关键字去调用
function Person(name, age) {
this.name = name;
this.age = age;
}
var p1 = new Person('lili',10);
console.log(p1);
for…in
用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。
var obj = {
a: "aline",
b: "browser",
c: "cat"
}
for(var v in obj){
document.write(v);
}
正则表达式
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。
搜索模式可用于文本搜索和文本替换。
/正则表达式主体/修饰符(可选)
var patt = /runoob/i
/runoob/i 是一个正则表达式。
runoob 是一个正则表达式主体 (用于检索)。
i 是一个修饰符 (搜索不区分大小写)。
使用字符串方法
在 JavaScript 中,正则表达式通常用于两个字符串方法 : search() 和 replace()。
search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置。
replace() 方法用于在字符串中用一些字符串替换另一些字符串,或替换一个与正则表达式匹配的子串。
修饰符 | 描述 |
---|---|
i | 执行对大小写不敏感的匹配。 |
g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。 |
m | 执行多行匹配。 |
使用forEach()方法遍历数组
1.参数
forEach()方法有一个参数,是一个回调函数的引用,每访问一个元素,调用一次回调函数
2.回调函数的参数
第一个参数,表示当前遍历的元素
第二个参数,表示当前遍历的元素的索引(下标)
第三个参数,表示当前正在遍历的数组
var array = [5, 3, 2, 8, 5, 6, 4, 7];
array.forEach(function(value, index, array){
if(index == 0){//仅在访问第一个元素时
console.log("array : " + array);
}
console.log(index + " : " + value);
});
箭头函数(阿曼达表达式)
定义:
ES6允许使用“箭头”(()=>{}) 定义函数
通俗的理解 箭头函数就是return函数
() => {}
eg:
let xx = ()=> 555
console.log( xx() )
就等同于:
function xx2() {
return 666;
}
console.log( xx2())
箭头函数的语法:
1,()中定义参数,如果只有一个参数,可以不写括号(如果有很多参数就可以在括号中用",”隔开);
2,{}中写函数体,如果函数体中只有返回值,可以不写return;
就得出箭头函数与普通函数的区别:
this指向不同:
普通函数,谁调用this this就指向谁
箭头函数,在哪里定义函数 this就指向谁
(可以理解为,内部的箭头函数不会改变this指向对象的,this仍然指向外面函数的作用域)
var和let和const
var可以重复定义一个变量,它是函数作用域,除在函数里面声明的变量为局部变量外其他的都是全局变量,如果一个变量前面不加var也默认是全局变量
var name;
var name; //合法
let不能重复定义一个变量,但可以在不同的块级作用域下可以定义一样的变量,它是块级作用域只在块级作用下才能起作用
if(){
let name;
let name;//不合法
}
console.log(name);//不行
const也是块级作用域,声明时必须赋值,不能重复定义
变量提升和函数提升
console.log(a); //未定义的
var a = "a";
var foo = () => {
console.log(a);//未定义的
var a = "a1";
}
foo();
等价与
var a;
console.log(a);
a = "a";
var foo = () => {
var a
console.log(a);
a = "a1";
}
foo();
回调函数
函数以一个实参的类型传了进去,而且该函数在这个函数执行完在继续执行
function execute (someFunction, value) {
someFunction(value);
}
execute(function(value){alert(value);}, 'hi js.');
节流阀
举个例子
比如我们要写一个轮播图,这个轮播图有两个按钮左右按钮,我们点击一个按钮想让他使得这个连续点击这个按钮不让这个图快速的播放
其实就是利用上面的回调函数去控制让上一个函数结束后在进行下一个
阻止事件的冒泡
e.stopPropagation();
哪些事件没有冒泡
load unload scroll resize blur focus mouseleave mouseenter
原型和原型链
一、什么是原型
原型是对象。包括显式原型对象和隐式原型对象。
显式原型对象:只有函数对象①才有显式原型对象,如下代码所示,函数的prototype属性就是显式原型对象,默认指向空对象。
注意:在函数的prototype属性添加属性(一般是方法),该函数对应的实例都会获得该属性的使用权。
function Fn(){}//函数对象才会有显式原型
console.log(Fn.prototype)//函数的prototype属性就是显式原型对象
隐式原型对象:只要是对象都会有隐式原型对象,并且它的值与该对象对应的构造函数的显式原型对象相等。如下代码所示:
function Fn(){}//函数对象才会有显式原型
console.log(Fn.prototype)
var fn = new Fn()
console.log(fn.__proto__)//所有对象都会有隐式原型
//实例对象隐式原型的值 等于 函数对象显式原型的值
console.log(fn.__proto__ === Fn.prototype)
Fn.prototype.test = function(){console.log('test')}
fn.test()//输出test
①:js中所有的都是对象,函数是一种特殊的对象
二、原型链
原型链实际是隐式原型链 ,具体如下
访问一个对象的属性时,先在自身属性中查找,找到则返回;如果没有,再沿着__proto__这条链向上查找,在自身对应的构造函数显式原型对象中查找,找到则返回;如果最终没找到,返回undefined;原型链的终点是Object的__proto__,也即返回null(object的__proto__是null)。
函数的闭包以及闭包的作用
1-什么是闭包:
闭包是指有权访问另一个函数作用域中变量的函数。通俗来说就是 ,一个作用域可以访问另外一个函数内部的局部变量。
// An highlighted block
function fn(){
var num=10;
function fn1(){
console.log(num);//10
}
fn1();
}
fn();
//fn就是一个闭包函数
21闭包的作用:
延伸变量的作用范围
function fn() {
var num = 10;
function fun() {
console.log(num);
}
return fun;
}
var f = fn();
f();
函数的四种调用方法
1、作为一个函数调用:直接调用函数
function abc(x,y) {
return x * y;
};
// console.log(abc(5,6));
console.log(window.abc(6,8));
2、作为方法来调用函数:将函数定义为对象的方法
var obj = {
name:"yoe",
age:22,
last:function () {
return this.name + " " + this.age;
},
};
console.log(obj.last());
//修改last方法,返回this值
//函数作为方法调用,使this的值成为对象本身
var obj = {
name:"yoe",
age:22,
last:function () {
return this;
},
};
console.log(obj.last());
(last方法是一个函数,obj是函数的所有者)
3、使用构造函数调用函数:(函数调用前使用new关键字)
//构造器调用会创建新对象。新对象会从构造器中继承属性即方法
//函数构造器
function dee(a,b) {
//构造器中的this没有值
this.one = a;
this.two = b;
}
//创建新的对象
//this的值在调用对象时创建
var obj = new dee("ele","vent");
console.log(obj.two);
4、作为函数方法调用函数:(call和apply是预定义的函数)
call() 方法可以接收多个参数列表,
apply() 方法只能接收数组形式的参数,数组元素将作为参数列表传递给被调用的函数
两个方法的第一个参数必须是对象本身(也可以是null)
当第一个参数为null时,得到的是当前运行环境的全局变量(window)
//call()方法 函数名.call()
function def(x,y) {
return x + y;
};
var obj = console.log(def.call(obj,3,4));
//apply()方法 函数名.apply()
function def(x,y) {
return x + y;
};
//var arr = [14,5];
//var obj = console.log(def.apply(obj,arr));
var obj = console.log(def.apply(obj,[14,6]));
DOM
获取元素
document.querySelector()
document.getElementByld()
document.getElementsByTagName()
document.getElementByClassName()
document.querySelectorAll()
document.body //返回body元素对象
document.documentElement //返回html元素对象
自定义属性的操作
获取属性值
element.属性 获取属性值(元素自带的属性)
element.getAttribute(‘属性’) 主要获取自定义的属性我们程序员自定义的属性()
设置自定义属性
element.属性=’值‘ 设置内置属性值
element.setAttribute(‘属性’) 主要设置自定义的属性
自定义属性的操作
移除属性
element.removeAttribute(‘属性’);
BOM
定时器
元素偏移量offset系列
元素可视区client系列
元素scroll系列属性
深拷贝
js中深拷贝的方法
原生js中递归函数拷贝
将数据中所有的数据拷贝下来,对拷贝之后的数据进行修改不会影响到原数据 ,两个对象或数组不共享一块内存
<script>
let obj={
abc:'123',
def:[{a:1,b:2,c:3},{q:8,w:9}],
qwe:{e:4,f:5}
}
//需求将obj这个对象拷贝出一个新对象修改新对象的值不会影响原对象的值
//定义一个函数
function copyobj(oldobj){
//定义一个变量接收新对象
let newObj=null
//判断这个对象还是数组
//1.如果是数组
if(oldobj instanceof Array){
newObj=[]
oldobj.forEach(item => {
newObj = copyobj(item)
});
//2.如果是对象
}else if(oldobj instanceof Object){
newObj={}
for(var i in oldobj){
newObj[i]=copyobj(oldobj[i])
}
}else {
newObj=oldobj
}
return newObj
}
let news=copyobj(obj)
console.log(news);
</script>
Object.create()
Object.create() 实现的是深拷贝通过原型链的方式
new Object() 实现的浅拷贝修改原数据新拷贝的数据也会随之改变
<script>
let a1={
abc:'123',
def:[{a:1,b:2,c:3},{q:8,w:9}],
qwe:{e:4,f:5}
}
//new Object() 实现的浅拷贝修改原数据新拷贝的数据也会随之改变
let b1=new Object(a1)
console.log(b1); //{abc:'123',def:[{a:1,b:2,c:3}{q:8,w:9}],qwe:{e:4,f:5}}
b1.abc="qqqq"
console.log(a1,b1);
//a1对应的值{abc:'qqqq',def:[{a:1,b:2,c:3}{q:8,w:9}],qwe:{e:4,f:5}}
//b1对应的值{abc:'qqqq',def:[{a:1,b:2,c:3}{q:8,w:9}],qwe:{e:4,f:5}}
//Object.create() 实现的是深拷贝通过原型链的方式
var a = { rep: 'apple' }
var b = Object.create(a)
console.log(b); //{ rep: 'apple' }
b.rep='www'
console.log(a,b);// { rep: 'apple' },{ rep: 'www' }
</script>