js的执行机制
js是单线程
同步:前面一个任务执行结束之后,执行后一个
异步:异步任务,引擎放在一边,不进入主线程,而进入任务队列的任务
js通过浏览器解析,浏览器靠引擎解析
`回调函数`同步任务执行完之后,再回到任务队列里查看异步任务
常见的异步任务是:settimeout 、setInterval 、事件等等
<script>
setTimeout(()=>{
console.log("世界那么拥挤吗,多我一个聪明的人怎么了55555")
},1000)
console.log("11111")
setTimeout(()=>{
console.log("好想睡觉")
},0)
console.log("22222")
console.log("33333")
</script>
可以看到,拥有定时器的输出语句即使定了0秒,也是后面执行
对象
1、定义(字面量)
对象的定义通过{}来实现,{}里有函数与变量,但在对象里他们叫属性与方法。
对象的成员以键值对的形式出现,多个成员之间用逗号隔开。如下
let cat={
"name":"Tom",
"age":0,
"eat":()=>{
console.log("猫喜欢吃鱼")
}
}
console.log(cat)
2、 访问对象成员
对象名.成员
console.log("猫猫的名字"+cat.name)
console.log("猫猫的年龄"+cat.age)
cat.eat()
3、 对象成员遍历
使用 for ....in.....可以遍历对象成员
for(let i in cat){
console.log(i+":"+cat[i])
}
构造函数
构建对象是创造对象的另一种方式
构造函数可以创造出一组具有相同特征的对象
可以通过动物函数构造出小猫,小狗,小鸟对象。这些对象基于构造函数这一个模板创造,同时又各有自己的特征。
定义1、
function 函数名(参数){
let 对象名={} //创建一个空对象
对象名.属性=参数
对象名.方法名=()=>{方法内容}
return 对象名
}
<script>
function a(name,age,action){
let animal={}
animal.name=name
animal.age=age
animal.action=action
animal.happy=()=>{console.log("冬暖夏凉,吃好睡好")}
return animal
}
let cat=a("小猫",9,"喵喵叫")
let dog=a("小狗",5,"汪汪叫")
console.log(cat)
console.log(dog)
</script>
定义2
function 对象名(参数){
this.参数=参数值
this.方法=function(){
方法内容
}}
function animal(name,age,action){
this.name=name
this.age=age
this.happy = function() {
console.log("睡个12个小时")}
this.hobby=()=>{
console.log("吃吃吃,好吃爱吃")}
}
let cat =new animal("猫咪",2,"喵喵喵")
let dog =new animal("狗狗",2,"汪汪汪")
console.log(cat)
console.log(dog)
cat.hobby()
深拷贝与浅拷贝
浅拷贝 : 指两个js 对象指向同一个内存地址,其中一个改变会影响另一个;
<script>
let a=[1,2,3,4]
let a2=a
a2.push("kaka")
console.log(a)
console.log(a2)
</script>
将数组a赋值与于a 2,a2发生改变,a也随之发生改变,是因为数组a将地址赋给了a2
深拷贝 :真正创建一个对象的副本,就是复制一个对象,复制后的新对象重新指向一个新的内存地址,两个对象改变互不影响。
<script>
let a=[1,2,3,4]
let a2=[...a]
a2.push("kaka")
console.log(a)
</script>
但是,复制的对象里面有元素是个数组,拆开对象复制元素的时候,并没有拆开元素里的数组,等同于浅拷贝的地址赋值。
<script>
let a=[1,2,3,4,["哈哈"]]
let a2=[...a]
a2[4].push("kaka")
console.log(a)
console.log(a2)
</script>
解决方法:让被复制的相对应的数组元素 ,另外赋值为拆开的原数组元素
<script>
let a=[1,2,3,4,["哈哈"]]
let a2=[...a]
a2[4]=[...a[4]]
a2.push("kaka")
console.log(a)
console.log(a2)
</script>
原型
假如,由构造函数创建的多个对象里,都有个一模一样的属性或方法,那么有相同属性方法的不同对象创建,会浪费内存。于是就有原型的出现。
原型是一个对象,包括构造函数共同的属性方法。原型对象是通过构造函数的prototype属性创建的。
下面这个例子两个对象之间有相同的函数,用关系运算符就知道他们连地址都不一样。
function animal(name,age,action){
this.name=name
this.age=age
this.hobby=()=>{
console.log("吃吃吃,好吃爱吃")}
}
let cat =new animal("猫咪",2,"喵喵喵")
let dog =new animal("狗狗",2,"汪汪汪")
console.log(cat.hobby===dog.hobby )
将同样的方法变成原型的共享方法 ,使其只占一块内存地址。
构造函数名.prototype.属性/方法
function animal(name,age,action){
this.name=name
this.age=age
}
let cat =new animal("猫咪",2,"喵喵喵")
let dog =new animal("狗狗",2,"汪汪汪")
animal.prototype.hobby=function (){
console.log("吃吃吃,好吃爱吃")}
console.log(cat.hobby===dog.hobby )
原型链
- 原型链:每个构造函数的原型对象都有一个指向另一个构造函数的原型对象的原型链。
- 当我们试图访问一个对象的属性时,如果该对象本身没有这个属性,会去查找创造这个对象的构造函数的原型对象。
- 若该原型对象本身没有这个属性,JS引擎会沿着原型链向上查找,直到找到该属性或者到达原型链的末端。
- 继承:通过原型链,JS实现了对象之间的继承。子级原型对象可以通过原型链访问父级原型对象的属性和方法,实现了属性和方法的共享。
- Object对象是js的内置对象,所有的 JS对象都继承自 Object的原型对象 Object.prototype,因为Object的原型对象是原型链的顶端。
- 原型链的终点是 null,在原型链的最顶端找不到属性或方法时会返回 null。
这是一个有原型的构造函数,所有对象有个共享方法happy。
function animal(name,age,action){
this.name=name
this.age=age
}
let cat =new animal("猫咪",2,"喵喵喵")
let dog =new animal("狗狗",2,"汪汪汪")
animal.prototype.hobby=function (){
console.log("吃吃吃,好吃爱吃")}
- console.log(cat.constructor)
- console.log(cat.__proto__.constructor)
- console.log(animal.prototype.constructor)
这三段语句都是下图结果,是构造函数本身
- console.log(cat.__proto__)
- console.log(animal.prototype)
这两句话指向同样的地方:构造函数原型对象
function animal(name,age) {
this.name=name
this.age=age;
}
const cat = new animal('猫咪', 10);
console.log(cat instanceof animal);
console.log(cat instanceof Object);
this
1、在全局作用域中
this -> window
<script>
console.log(this); //this->window
</script>
2、箭头函数中的this
箭头函数没有自己的this,引用的是距离自己最近的作用域中的this
3、事件绑定中的this
this -> 事件源
<button>点击</button>
document.querySelector("button").addEventListener("click",function(){
console.log(this)
})
4、定时器中的this
this->window
setTimeout(()=>{
console.log(this)
})
5、构造函数中的this
this->实例化对象
function animal(name,age){
this.name=name
this.age=age
this.hobby=function (){
console.log(this)
console.log(this.name)
console.log(this.age)
}
}
let cat =new animal("猫咪",2,"喵喵喵")
cat.hobby()
更改this指向
this的指向是可以改变的
call() 、 apply() 这2个函数的第一个参数都是 this 的指向对象
bind()
call()
<script>
let a={
name:"zhangsan"
}
let b={
name:"lisi",
ha:function(c,d){console.log(this.name+c+d)}
}
b.ha.call(a,"1","2")
</script>
apply()
<script>
let a={
name:"zhangsan"
}
let b={
name:"lisi",
ha:function(c,d){console.log(this.name+c+d)}
}
b.ha.apply(a,[1,2])
</script>
bind()
<!-- 不会调用函数,返回的是新函数 -->
<script>
function t(){
console.log(this)
}
const o={
"nan":"dfgh"
}
newa=t.bind(o)
newa()
</script>
综合
let name="lisi",age=5
let a={
name:"kawu",
aage:this.age,
p:function(n,aa){
console.log(this.name+","+this.aage+"岁"+"来自"+n+"去往"+aa)
}
}
let b={
aage:22,
name:"zhangsan"
}
function bb(ag){
console.log(this.nname+ag)
}
let nname="xiaoming"
let B=bb.bind({nname:"xiaohua"},2)
a.p.call(b,'成都','上海')
a.p.apply(b,['成都','上海']);
B()
异常处理:
final:不管有没有异常都会执行
下面这个例子故意没有写盒子标签
<body>
<script>
try{
const b=document.querySelector("div")
box.style.backgroundColor="red"
}catch(error){
console.log(error.message)
console.log("kakakakakak")
}
finally{
console.log("sdfghjkwertyuio")
}
</script>
</body>
function t(n1,n2){
if(n1!=n2){
throw new Error("nonononon");
}
}
t(3,4)
Jquery
- $是顶级对象,同时是jquary的别称
- jquary无法使用原生对象的方法
- $(dom对象)===转换为jQuary对象
- 要下载引入Jquery官网的js文件,其中压缩了大量属性与方法 <script src="./jquery-3.7.1.min.js"> </script>
- 引入js文件的标签里面就不要再写东西了,重新再写script标签去编写属性方法
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./jquery-3.7.1.min.js">
</script>
<style>
div{
height: 100px;
width: 200px;
border: 3px solid blue;
}
</style>
</head>
<body>
<div>好的佳人们</div>
<script>
$("div").css({"color": "aqua","backgroundColor" :"blue"})
</script>
</body>
</html>
入口函数
隐式迭代
选择器
练习
引入CSS样式:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./jquery-3.7.1.min.js">
</script>
<style>
div{
height: 100px;
width: 200px;
border: 3px solid blue;
}
.new{
height: 150px;
width: 150px;
border-radius: 50%;
background-color: chartreuse;
}
</style>
</head>
<body>
<div>好的佳人们</div>
<script>
$("div").addClass("new")
// $("div").removeClass("new")
// $("div").toggleClass("new")
</script>
</body>
</html>