3.4JavaScript网页编程——JS高级(可以不看)

JS高级教程

学会查文档ReferenceAPI函数
进阶版笔记有点乱,可以看百度网盘的JS高级教程md笔记

回忆

BOM:浏览器对象模型
window:navigator、location、history、screen、document(window下面的对象)
window:load、DOMContentLoaded、beforeunload(离开页面触发)、
dragover、drop
classList:add、remove、toggle、contains
自定义属性:data-xxx、dataset

关于JS的零碎补充

  1. 如果没有let,默认是全局变量,那么在函数外面就可以使用(全局变量污染),不建议不写let
    3.4JavaScript网页编程——JS高级(可以不看)_第1张图片
  2. ES6中{}大括号包裹的代码块等价于局部作用域局部变量,括号外不能使用,
  3. let 声明的变量产生块作用域(window对象下没有),var 不会产生块作用域事全局变量(window对象里面有)
  4. const 声明的常量也会产生块作用域,推荐使用 letconst(const声明的不能改变,其余和let没什么区别)
  5. 作用域链本质上是底层的变量查找机制,在函数被执行时,会优先查找当前函数作用域中查找变量,如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域,往上查找变量
    答案:456(n=456是全局的被改变了)
    3.4JavaScript网页编程——JS高级(可以不看)_第2张图片
  6. arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的 所有实参,作用是动态获取函数的实参。
<script>
  // 求生函数,计算所有参数的和
  function sum() {
    // console.log(arguments);
    let s = 0;
    for(let i = 0; i < arguments.length; i++) {
      s += arguments[i];
    }
    console.log(s);
  }

  // 调用求和函数
  sum(5, 10); // 两个参数
  sum(1, 2, 4); // 两个参数
script>
  1. 函数没传参的时候,形参是undefined,两个相加是NAN,并且NAN === NAN是false
    3.4JavaScript网页编程——JS高级(可以不看)_第3张图片
  • 剩余参数:只能用于最后一个形参,表示剩余的所有参数
  • 当然括号内只有一个形参且为剩余参数时,则表示所有的参数fun(…a)
  • … 是语法符号,置于最末函数形参之前,用于获取多余的实参,借助 … 获取的剩余实参
    3.4JavaScript网页编程——JS高级(可以不看)_第4张图片
    3.4JavaScript网页编程——JS高级(可以不看)_第5张图片
  1. 对象.属性(这个属性不能是变量,否则就变量名是属性了,和对象[‘属性’](这里括号里可以换成变量),比如obj.str[i]这样指代的是属性名为str[i]…,而只能对象[str[i]]

预解析

代码在执行之前,任何一个作用域都要预解析,解析变量和函数(也就是只解析定义的函数,不解析调用的和回调函数,其实原理和BOM里面的队列栈线程的同步异步类似)。这样,预解析解析完了再执行,即便先调用,再声明,不会报错,是undefined,函数内部还有就继续被解析,但是let的声明不会被解析,就会报错
在这里插入图片描述

在这里插入图片描述
3.4JavaScript网页编程——JS高级(可以不看)_第6张图片
变量:带有申明的变量才会进行变量解析,变量提升,JS会把申明的变量,提升到当前作用域的最前面,只申明不赋值

函数:代有函数名的变量才会进行函数解析(回调函数和函数表达式不会被解析),函数提升,JS会把带有名字的函数,提升到当前作用域最前面,只定义不调用

<script>
  // 调用函数
  foo();

  // 声明函数(会解析,被提前)
  function foo() {
    console.log('声明之前即被调用...');
  }

  // 不存在提升现象
  bar();
  var bar = function () {
    console.log('函数表达式不存在提升现象...');
  }
script>

死区:let声明之前的,不会被解析,报错!!
但是下面代码如果var则可以,输出undefined

3.4JavaScript网页编程——JS高级(可以不看)_第7张图片

下面练习,

  • 答案是:两个undefined,(简便想就是先调用再声明的代码,只要声明的是可以被解析的那就undefined,不能被解析的就报错)

3.4JavaScript网页编程——JS高级(可以不看)_第8张图片

  • 答案是函数(){}和2
    3.4JavaScript网页编程——JS高级(可以不看)_第9张图片

闭包

闭包是一种比较特殊和函数,使用闭包能够访问函数作用域中的变量。从代码形式上看闭包是一个做为返回值的函数,
闭包:一个作用域有权访问另外一个作用域的局部变量,
在这里插入图片描述

好处:可以把一个变量使用范围延伸

  1. 闭包本质仍是函数,只不是从函数内部返回的
  2. 闭包能够创建外部可访问的隔离作用域,避免全局变量污染
  3. 过度使用闭包可能造成内存泄漏

3.4JavaScript网页编程——JS高级(可以不看)_第10张图片

<script>
  function foo() {
    let i = 0;

    // 函数内部分函数
    function bar() {
			console.log(++i);
    }

    // 将函数做为返回值
    return bar;
  }
  
  // fn 即为闭包函数
  let fn = foo();
  
  fn(); // 1
script>
  • 注:回调函数也能访问函数内部的局部变量。
    3.4JavaScript网页编程——JS高级(可以不看)_第11张图片

箭头函数

箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上。

  1. 箭头函数属于表达式函数,因此不存在函数提升
  2. 箭头函数只有一个参数时可以省略圆括号 ()
  3. 箭头函数函数体只有一行代码时可以省略花括号 {},并自动做为返回值被返回
  4. 箭头函数中没有 arguments,只能使用 ... 动态获取实参
  5. 涉及到this的使用,不建议用箭头函数
    3.4JavaScript网页编程——JS高级(可以不看)_第12张图片

3.4JavaScript网页编程——JS高级(可以不看)_第13张图片

  • 1.当没有参数,小括号可以不写
<script>
  // 箭头函数
  let foo = () => {
    console.log('^_^ 长相奇怪的函数...');
  }
  // 调用函数
  foo();
  
  // 更简洁的语法
  let form = document.querySelector('form');
  form.addEventListener('click', ev => ev.preventDefault());
script>
  • 2.函数体只返回一行时,可以省略大括号和return
    3.4JavaScript网页编程——JS高级(可以不看)_第14张图片
    箭头函数的使用场景如下(定时器的this也是指向window或者事件源的)
    3.4JavaScript网页编程——JS高级(可以不看)_第15张图片

  • 3.箭头函数没有预解析,所以必须先定义再调用

  • 4.箭头函数中,不存在arguments
    3.4JavaScript网页编程——JS高级(可以不看)_第16张图片
    所以要换成…a,这样就可以获取输入的数组了
    3.4JavaScript网页编程——JS高级(可以不看)_第17张图片

  • 5.谁调用箭头函数,箭头函数里面的this就指向谁(箭头函数认为没有this,所以里面不要使用this而使用元素.什么)

  • 普通函数是window调用哦,这个this指向window
    3.4JavaScript网页编程——JS高级(可以不看)_第18张图片

  • 匿名函数,事件源里面的这个this指向的事件源(事件调用者),也就是btn
    在这里插入图片描述在这里插入图片描述
    对象里面含有属性,也有方法,调用的时候是对象调用,所以this指向对象
    3.4JavaScript网页编程——JS高级(可以不看)_第19张图片

  • 箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),此处指父级作用域,而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this

下面是箭头函数和匿名函数的比较!!!(匿名会指向当前调用的对象,但是箭头函数多数为window)

var s = 21;
const obj = {
    s: 42,
    m: () => console.log(this.s),
    k: function(){console.log(this.s)}
};
obj.m();	// 21
obj.k();	// 42
<button>789798button>

<script>
    let btn = document.querySelector('button')
    // 匿名函数的调用
    // btn.addEventListener('click',function(){
    //     //console.log(this);      //
    //     this.style.backgroundColor = 'red' //按钮变红
    // },false);
	
	//箭头函数
    btn.addEventListener('click',() => {
        console.log(this);      //window{window:.....}
        this.style.backgroundColor = 'red' //报错
    },false);

script>

3.4JavaScript网页编程——JS高级(可以不看)_第20张图片

如果上图是匿名函数,两个this分别指向调用者,也就是window和document

  1. call 方法能够在调用函数的同时指定 this 的值
  2. 使用 call 方法调用函数时,第1个参数为 this 指定的值
  3. call 方法的其余参数会依次自动传入函数做为函数的参数
<script>
  // 普通函数
  function sayHi() {
    console.log(this);
  }

  let user = {
    name: '小明',
    age: 18
  }

  let student = {
    name: '小红',
    age: 16}

  // 调用函数并指定 this 的值
  sayHi.call(user); // this 值为 user
  sayHi.call(student); // this 值为 student

  // 求和函数
  function counter(x, y) {
    return x + y;
  }

  // 调用 counter 函数,并传入参数
  let result = counter.call(null, 5, 10);
  console.log(result);
script>

this的改变

call

使用 call 方法调用函数,同时指定函数中 this 的值,改变原有的this指向
3.4JavaScript网页编程——JS高级(可以不看)_第21张图片
这样obj就是o对象了

apply

<script>
  // 普通函数
  function sayHi() {
    console.log(this);
  }

  let user = {
    name: '小明',
    age: 18
  }

  let student = {
    name: '小红',
    age: 16
  }

  // 调用函数并指定 this 的值
  sayHi.apply(user); // this 值为 user
  sayHi.apply(student); // this 值为 student

  // 求和函数
  function counter(x, y) {
    return x + y;
  }

  // 调用 counter 函数,并传入参数
  let result = counter.apply(null, [5, 10]);
  console.log(result);
script>
  1. apply 方法能够在调用函数的同时指定 this 的值
  2. 使用 apply 方法调用函数时,第1个参数为 this 指定的值
  3. apply 方法第2个参数为数组,数组的单元值依次自动传入函数做为函数的参数

bind

bind 方法并不会调用函数,而是创建一个指定了 this 值的新函数,要执行就使用()进行调用,此时对象是李寻欢
3.4JavaScript网页编程——JS高级(可以不看)_第22张图片
点击五秒禁用,五秒后启用
3.4JavaScript网页编程——JS高级(可以不看)_第23张图片
bind 方法创建新的函数,与原函数的唯一的变化是改变了 this 的值。

三者区别

call:fun.call(this,arg1, arg2,…)
apply:fun.apply(this, [arg1, arg2,…])
bind:fun.bind(this, arg1, arg2,…)

  • 相同点:
    都可以用来改变this指向,第一个参数都是this指向的对象
  • 区别:
    call和apply:都会使函数执行,但是参数不同
    bind:不会使函数执行,参数同call

解构

解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。

  • 数组解构(其中也可以用…)
    数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法
    1.赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
    2.变量的顺序对应数组单元值的位置依次进行赋值操作
    3.变量的数量大于单元值数量时,多余的变量将被赋值为 undefined
    4.变量的数量小于单元值数量时,可以通过 ... 获取剩余单元值,但只能置于最末位
    5.允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效
    在这里插入图片描述
<script>
  // 普通的数组
  let arr = [1, 2, 3];
  // 批量声明变量 a b c 
  // 同时将数组单元值 1 2 3 依次赋值给变量 a b c
  let [a, b, c] = arr;
  console.log(a); // 1
  console.log(b); // 2
  console.log(c); // 3
script>
  • 对象解构
    1.对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法
    2.赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
    3.对象属性的值将被赋值给与属性名相同的变量
    4.对象中找不到与变量名一致的属性时变量值为 undefined
    5.允许初始化变量的默认值,属性不存在或单元值为 undefined 时默认值才会生效

3.4JavaScript网页编程——JS高级(可以不看)_第24张图片
为了防止和外面的变量重,
3.4JavaScript网页编程——JS高级(可以不看)_第25张图片
对象解构
3.4JavaScript网页编程——JS高级(可以不看)_第26张图片3.4JavaScript网页编程——JS高级(可以不看)_第27张图片

答案是5个9最后一个报错

3.4JavaScript网页编程——JS高级(可以不看)_第28张图片

对象

字面量创建对象

3.4JavaScript网页编程——JS高级(可以不看)_第29张图片
3.4JavaScript网页编程——JS高级(可以不看)_第30张图片

构造函数创建new 创建

1.构造函数是专门用于创建对象的函数,如果一个函数使用 new 关键字调用,那么这个函数就是构造函数。
2.使用 new 关键字调用函数的行为被称为实例化
3.实例化构造函数时没有参数时可以省略 ()
4.构造函数的返回值即为新创建的对象
5.构造函数内部的 return 返回的值无效!
6.实践中为了从视觉上区分构造函数和普通函数,习惯将构造函数的首字母大写。

  • 自定义构造函数
    3.4JavaScript网页编程——JS高级(可以不看)_第31张图片
  • obj instanceof B用于检测实例对象对应的构造函数
  • 实例对象的 obj.constructor 属性指向了对象的构造函数

3.4JavaScript网页编程——JS高级(可以不看)_第32张图片

创建对象除了常规的那种,属性还可以放在constructor里面
3.4JavaScript网页编程——JS高级(可以不看)_第33张图片

实例成员和静态成员

实例成员:通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。

  1. 构造函数内部 this 实际上就是实例对象,为其动态添加的属性和方法即为实例成员
  2. 为构造函数传入参数,动态创建结构相同但值不同的对象
  3. 实例对象的 constructor 属性指向了构造函数
  4. instanceof 用于检测实例对象对应的构造函数
    注:构造函数创建的实例对象彼此独立互不影响。
<script>
  // 构造函数
  function Person() {
    // 构造函数内部的 this 就是实例对象

    // 实例对象中动态添加属性
    this.name = '小明';
    // 实例对象动态添加方法
    this.sayHi = function () {
      console.log('大家好~');
    }
  }

  // 实例化,p1 是实例对象
  // p1 实际就是 构造函数内部的 this
  let p1 = new Person();

  console.log(p1);
  console.log(p1.name); // 访问实例属性
  p1.sayHi(); // 调用实例方法
script>

静态成员:在 JavaScript 中底层函数本质上也是对象类型,因此允许直接为函数动态添加属性或方法,构造函数的属性和方法被称为静态成员

  1. 静态成员指的是构造函数本身的属性和方法(类本身的)
  2. 一般公共特征的属性或方法静态成员设置为静态成员
  3. 静态成员方法中的 this 指向构造函数本身
<script>
  // 构造函数
  function Person(name, age) {
    // 省略实例成员
  }

  // 静态属性
  Person.eyes = 2;
  Person.arms = 2;
  // 静态方法
  Person.walk = function () {
    console.log('^_^人都会走路...');
    // this 指向 Person
    console.log(this.eyes);
  }
script>

3.4JavaScript网页编程——JS高级(可以不看)_第34张图片

3.4JavaScript网页编程——JS高级(可以不看)_第35张图片
构造函数也是对象,可以通过.方法或者属性

在这里插入图片描述

引用类型Object、Array、RegExp

Object:是内置的构造函数,用于创建普通对象。
Array:是内置的构造函数,用于创建数组。
RegExp:内置的构造函数,用于创建正则表达式

  • 简单数据类型(值传递),引用类型和复杂类型是引用传递,是在栈里面复制一个地址把地址传给他,堆里面还是那个数据

Object

3.4JavaScript网页编程——JS高级(可以不看)_第36张图片

Array

张飞会变张辽的
3.4JavaScript网页编程——JS高级(可以不看)_第37张图片

  • 学会查文档ReferenceAPI函数
    下面只是列举一些
    3.4JavaScript网页编程——JS高级(可以不看)_第38张图片
    任何一个属性都是Array构造函数的实例化对象
    所以也可以用ary instance of Array //true
    3.4JavaScript网页编程——JS高级(可以不看)_第39张图片
    join引号里面可以加字符之间的符号,这里是’‘也就是无间隔,也可以’-'进行相连(字符串里面split以拆分)
    3.4JavaScript网页编程——JS高级(可以不看)_第40张图片
    sort和正序倒序,正序就是从小到大
    3.4JavaScript网页编程——JS高级(可以不看)_第41张图片
    foreach遍历方便
    3.4JavaScript网页编程——JS高级(可以不看)_第42张图片

3.4JavaScript网页编程——JS高级(可以不看)_第43张图片
find()

3.4JavaScript网页编程——JS高级(可以不看)_第44张图片
findIndex
3.4JavaScript网页编程——JS高级(可以不看)_第45张图片
some和every

3.4JavaScript网页编程——JS高级(可以不看)_第46张图片
filter和Map
3.4JavaScript网页编程——JS高级(可以不看)_第47张图片

RegExp

3.4JavaScript网页编程——JS高级(可以不看)_第48张图片
3.4JavaScript网页编程——JS高级(可以不看)_第49张图片

包装类型

在 JavaScript 中的字符串、数值、布尔具有对象的使用特征,如具有属性和方法,之所以具有对象特征的原因是字符串、数值、布尔类型数据是 JavaScript 底层使用 Object 构造函数“包装”来的,被称为包装类型。(MDN网站查找文档)

  • String
  • Number
  • Boolean

1.String

3.4JavaScript网页编程——JS高级(可以不看)_第50张图片
取出字符串某个字符,以及trim()
3.4JavaScript网页编程——JS高级(可以不看)_第51张图片
split(‘’)把字符串分割单个字符,如果是c那就分割成以c分割的字符串)
toLowerCase变成小写,toUpperCase都为大写

3.4JavaScript网页编程——JS高级(可以不看)_第52张图片
indexOf(‘字符/字符串’),查找元素第一次出现的位置、lastIndexOf()
3.4JavaScript网页编程——JS高级(可以不看)_第53张图片
slice(start, end)字符串截取(数组的截取是splice(start, length))、substring(start, end)也是截取、substr(start,length)也是

3.4JavaScript网页编程——JS高级(可以不看)_第54张图片

2.Number

3.4JavaScript网页编程——JS高级(可以不看)_第55张图片

3.4JavaScript网页编程——JS高级(可以不看)_第56张图片
3.4JavaScript网页编程——JS高级(可以不看)_第57张图片

<script>
  // 使用构造函数创建布尔类型
  let locked = new Boolean('10');

  // 字面量创建布尔类型
  let flag = true;

  // 检测是否属于同一个构造函数
  console.log(locked.constructor === flag.constructor);
script>

总结

JavaScript 中一切皆为对象,还有以前学习的 window、Math 对象,最后补充一点无论是引用类型或是包装包类型都包含两个公共的方法 toStringvalueOf

  1. valueOf 方法获取原始值,数据内部运算的基础,很少主动调用该方法
  2. toString 方法以字符串形式表示对象
  3. Null、undefined:除外
<script>
  // 对象类型数据
  let user = {name: '小明', age: 18}
  // 数值类型	 
  let num = 12.345;
  // 字符串类型
  let str = 'hello world!';
  
  str.valueOf(); // 原始值
  user.toString(); // 表示该对象的字符串
script>

3.4JavaScript网页编程——JS高级(可以不看)_第58张图片

原型对象

实际上每一个构造函数都有一个名为 prototype 的属性,译成中文是原型的意思,prototype 的是对象类据类型,称为构造函数的原型对象,每个原型对象都具有 constructor 属性代表了该原型对象对应的构造函数。

  • 我的理解

1.实际上prototype的话就可以去增添方法那些,后面实例化的对象都可以使用了,一般普通实例化的对象是不会对prototype的方法属性增添的,

2.还有就是如果实例化的对象自己有那个方法就优先用自己的,否则就使用prototype的)

3.4JavaScript网页编程——JS高级(可以不看)_第59张图片

  • 看一个有意思的,简直是你中有我我中有你,

3.4JavaScript网页编程——JS高级(可以不看)_第60张图片
如果实例化的对象,本身没有prototype,就会通过自身的constructor构造函数去找原型对象prototype

3.4JavaScript网页编程——JS高级(可以不看)_第61张图片

原型链

在 JavaScript 对象中包括了一个非标准备的属性 proto 它指向了构造函数的原型对象,通过它可以清楚的查看原型对象的链状结构。
3.4JavaScript网页编程——JS高级(可以不看)_第62张图片

继承

  • extends 是 ECMAScript 6 中实现继承的简洁语法,是专门用于实现继承的语法关键字,Person 称为父类、Chinese 称为子类。
<script>
  class Person {
    // 父类的属性
    legs = 2;
    arms = 2;
    eyes = 2;
		// 父类的方法
    walk () {
      console.log('人类都会走路...');
    }
		// 父类的方法
    sleep () {
      console.log('人都得要睡觉...');
    }
  }

  // Chinese 继承了 Person 的所有特征
  class Chinese extends Person {}

  // 实例化
  let c1 = new Chinese(); //c1也有那些属性和方法
  c1.walk();
script>
  • super

在继承的过程中子类中 constructor 中必须调 super 函数,否则会有语法错误,子类构造函数中的 super 函数的作用是可以将子类实例化时获得的参数传入父类的构造函数之中。
3.4JavaScript网页编程——JS高级(可以不看)_第63张图片

<script>
  class Person {
    // 构造函数
    constructor (name, age) {
      this.name = name;
      this.age = age;
    }
    
    // 父类的属性
    legs = 2;
  	arms = 2;
  
    walk () {
      console.log('人类都会走路...');
    }
  }

  // 子类 English 继承了父类 Person
  class English extends Person {
    // 子类的构造函数
    constructor (name, age) {
      super(name, age);
    }

    // 子类的属性
    skin = 'white';
  	language = '英文';
    }

  // 实例化
  let e1 = new English('jack', 18);
  console.log(e1.name);
script>

拷贝

ECMAScript 6 中基于类的面向对象相较于构造函数和原型对象的面向对象本质上是一样的,基于类的语法更为简洁,未来的 JavaScript 中也都会是基于类的语法实现,当前阶段先熟悉基于类的语法,后面课程中会加强基于类语法的实践。
拷贝不是直接赋值(赋值的对象是改一个另一个改,传的地址)
浅拷贝:

含义:只拷贝最外面层的拷贝方式
	let obj = {
			uname : '张三丰',
			age : 22,
			sex : '男',
			color : ['red', 'blue', 'yellow', 'pink'],
			message : {
				index : 1,
				score : 99
			}
		}

		let newObj = {};

		Object.assign(newObj, obj);

		console.log( obj, newObj );

深拷贝:

你可能感兴趣的:(前端,javascript,前端,开发语言)