赞
踩
大家好,小编来为大家解答以下问题,javascript高级程序设计和权威指南,javascript高级语言程序设计,现在让我们一起来看看吧!
(1)、 面向过程编程:
ES6
中的类和对象JavaScript
中,对象是一组无序的相关属性和方法的集合,所有的事务都是对象,例如:字符串、数值、数组、函数等;class
)ES6
中新增加了类的概念,可以使用class
关键字声明一个类,之后以这个类来实例化对象;class
);- class name(){
- //class body
- }
var xx = new name();
new
实例化对象;constructor()
(构造函数 又叫 构造器)constructor()
方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new
命令生成对象实例时,自动调用该方法。如果没有显示定义,类内部会自动给我们创建一个constructor()
;- //1、创建类 class 创建一个明星类
- class Star{
- //类的共有属性放到 constructor 里面;
- constructor(uname){//接收实例传递过来的参数并返回实例对象;
- this.uname = uname;
- }
- }
- //2、利用类创建对象 new
- var ldh = new Star('刘德华');
- console.log(ldh.uname);//刘德华
class
关键字创建类,类名我们还是习惯性定义首字母大写;constructor()
函数,可以接受传递过来的参数,同时返回实例对象;constructor
函数只要new
生成实例时,就会自动调用这个函数,如果我们不写这个函数,类也会自动生成这个函数;new
不能省略;function
;- class Person{
- constructor(name,age){//constructor 构造器 或 构造函数
- this.name = name;
- this.age = age;
- }
- say(){
- console.log(this.name + '你好');
- }
- }
- //1、类里面所有的函数不需要写function;
- //2、多个函数方法之间不需要添加逗号分隔;
extends
和super
关键字extends
关键字- class Father{//父类
- constructor(){
-
- }
- money(){
- console.log(100);
- }
- }
- class Son extends Father{//子类继承父类
- }
- var son = new Son();
- son.money();//100
super
关键字super
关键字用于访问和调用对象父类上的函数快码论文。可以调用父类的构造函数,也可以调用父类的普通函数;- class Father{
- constructor(x,y){
- this.x = x;
- this.y = y;
- }
- sum(){
- console.log(this.x + this.y);
- }
- }
- class Son extends Father{
- constructor(x,y){
- super(x,y);//调用了父类中的构造函数
- }
- }
- var son = new Son(1,2);
- son.sum();

super
关键字调用父类的普通函数;- class Father{
- say(){
- return '我是爸爸';
- }
- }
- class Son extends Father{
- say(){
- console.log(super.say() + '的儿子');//调用父类的say方法
- }
- }
- var son = new Son();
- son.say();
super
必须放到子类this
之前;super
,必须放到this
前面(必须先调用父类的构造方法,再使用子类构造方法);- //父类有加法方法
- class Father{
- constructor(x,y){
- this.x = x;
- this.y = y;
- }
- sum(){
- console.log(this.x + this.y);
- }
- }
- //子类继承父类加法方法,同时,扩展减法方法;
- class Son extends Father{
- constructor(x,y){
- super(x,y);//super必须在子类this之前调用,否咋会报错
- this.x = x;
- this.y = y;
- //利用super 调用父类的构造函数;
- }
- subtract(){
- console.log(this.x - this.y);
- }
- }
- var son = new Son(5,3);
- son.subtract();

ES6
中类没有变量提升,所以必须先定义类,才能通过类实例化对象;this
使用;(this
指向是实例化对象)this
指向问题;- //案例:点击button调用sing方法
- <button>点击</button>
- var that;
- var _that;
-
- class Star{
- constructor(uname,age){
- //constructor里面的this指向的是【创建的实例对象】;
- that = this;
-
- this.uname = uname;
- this.age = age;
- //this.sing();
- this.btn = document.querySelector('button');
- //实例对象的btn,所以要加this;
- //点击会输出undefined;原因:sing里面的this指向的是btn;而btn里面是没有uname属性的,所以打印出来的是undefined;
- this.btn.onclick = this.sing;//此处sing后面不需要加小括号,因为不需要立马就调用,而是要点击按钮再调用;
- }
- sing(){
- //这个sing方法里面的this指向的是btn这个按钮,因为这个按钮调用了这个函数;
- console.log(this.uname);//从实例上拿uname,所以需要加this
- console.log(that.uname);//that里面存储的是constructor里面的this;所以打印出来的是刘德华;
-
- }
- dance(){
- //这个dance里面的this,指向的是实例对象 ldh,因为ldh调用了这个函数;
- _that = this;
- }
- }
- var ldh = new Star('刘德华');

this
指向问题;constructor
里面的this
指向实例对象,方法里面的this
指向这个方法的调用者;tab
栏切换new
一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面;JS
中,使用构造函数时要注意以下两点:new
一起使用才有意义;new
在执行时会做四件事:this
指向这个新的对象;return
);java
),都存在类的概念,类就是对象的模版,对象就是类的实质,但在ES6
之前,JS
中并没有引入类的概念;ES6
全称ECMAScript6.0
2015.06发布。但是目前浏览器的JavaScript
是ES5
版本,大多数高版本的浏览器也支持ES6
,不过只实现了ES6
的部分特性和功能;ES6
之前,对象不是基于类创建的,而是用一种称为【构建函数】的特殊函数来定义对象和他们的特征;{}
)new Object()
- // 1、利用new Object()创建对象;
- var obj1 = new Object();
-
- // 2、利用对象字面量创建对象;
- var obj2 = {};
- // 3、利用构造函数创建对象;
- function Star(uname,age){
- this.uname = uname;
- this.age = age;
- this.sing = function(){
- console.log('唱歌');
- }
- }
- //利用new关键字创建实例对象;
- var ldh = new Star('ldh',13);
- console.log(ldh);

JavaScript
的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的this
上添加。通过这两种方式添加的成员,就分别称为【静态成员】和【实例成员】。Star.sex='男'
,sex
就是静态成员),只能通过构造函数来访问(如:Star.sex
);this
添加的成员称为实例成员(如上面代码中的uname
、age
、sing
),只能由实例化的对象来访问(如:ldh.uname
);不可以通过构造函数(Star.uname
)来访问实例成员;prototype
prototype
分配的函数是所有对象所共享的;java
规定,每一个构造函数都有一个prototype
属性,指向另一个对象。注意这个prototype
就是一个对象(所以就称为原型对象),这个对象的所有属性和方法,都会被构造函数所拥有;prototype
对象上,这样所有对象的实例就可以共享这些方法;- function Star(uname,age){
- this.uname = uname;
- this.age = age;
- }
- //可以把那些不变的方法,直接定义在`prototype`原型对象上;
- Star.prototype.sing = function(){
- console.log('唱歌');
- }
- var ldh = new Star('ldh',19);
- var zxy= new Star('zxy',19);
- console.log(ldh.sing === zxy.sing);//true 比较的是方法的内存地址
- ldh.sing();
- zxy.sing();
prototype
为原型对象;__proto__
__proto__
,指向构造函数的prototype
原型对象,之所以我们对象可以使用构造函数prototype
原型对象的属性和方法,就是因为对象有__proto__
原型的存在;__proto__
对象原型和原型对象prototype
是等价的;__proto__
对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype;- console.log(ldh.__proto__ === Star.prototype);//true
- /*
- 方法的查找规则:
- (1)、首先看ldh对象身上是否有sing方法,如果有就执行这个对象上的sing;
- (2)、如果没有sing这个方法,因为有__proto__的存在,就去构造函数原型对象prototype身上去查找sing这个方法;
- */
constructor
构造函数__proto__
)和构造函数原型对象(prototype
)里面都有一个属性constructor
属性,constructor
我们称为构造函数,因为它指回构造函数本身;constructor
主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数;- function Star(uname,age){
- this.uname = uname;
- this.age = age;
- }
- //Star.prototype.sing = function(){
- // console.log('唱歌');
- //}
- //Star.prototype.movie= function(){
- // console.log('演电影');
- //}
-
- //很多情况下,我们需要手动的利用constructor这个属性指回 原来的构造函数;
- Star.prototype = {
- //如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数;
- constructor:Star,
- sing:function(){
- console.log('唱歌');
- },
- movie:function(){
- console.log('演电影');
- }
- }
- var ldh = new Star('刘德华',18);
- var zxy= new Star('张学友',18);
- console.log(Star.prototype);
- console.log(ldh.__proto__);

__proto__
原型,指向原型对象;Star
原型对象里面的__proto__
原型指向的是Object.prototype
;Object.prototype
原型对象里面的__proto__
原型,指向为null
;JavaScript
的对象成员查找规则(机制)__proto__
指向的prototype
原型对象);Object
的原型对象);Object
为止(null
);__proto__
对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线;this
指向this
到底指向谁只有调用的时候才会确定;this
指向的是调用者;- function Star(uname,age){
- this.uname = uname;
- this.age = age;
- }
- var that;
- Star.prototype.sing = function(){
- console.log('唱歌');
- that = this;
- }
- var ldh = new Star('刘德华',19);
-
- //1、在构造函数中,里面的this指向的是 实例对象 ldh;
- ldh.sing();
- console.log(that === adh);
- //2、原型对象函数里面的this 指向的是 实例对象 ldh;
- console.log(Array.prototype);//打印数组的原型
-
- Array.prototype.sum = function(){
- var sum = 0;
- for(var i = 0;i < this.length;i++ ){
- sum += this[i];
- }
- return sum;
- }
- var arr = [1,2,3];
- console.log(arr.sum());//6
-
- var arr1 = new Array(11,22,33);
- console.log(arr1.sum());//66
Array.prototype = {}
,只能是Array.prototype.xxx = function(){}
的方式;ES6
之前并没有给我们提供extends
继承。我们可以通过构造函数+原型对象模拟实现继承,被称为【组合继承】;call
把父类型的this
指向子类型的this
,这样就可以实现子类型继承父类型的属性;- <>
- // 借用父构造函数继承属性;
- // 1、父构造函数
- function Father(uname,age){
- // this 指向父构造函数的对象实例;
- this.uname = uname;
- this.age = age;
- }
-
- // 2、子构造函数
- function Son(uname,age,score){
- // this 指向子构造函数的实例对象;
- Father.call(this,uname,age);//调用父构造函数,把父构造函数中的this改为子构造函数中的this;
- this.score = score;
- }
- var son = new Son('刘德华',12,90);
- console.log(son);//Son {uname: '刘德华', age: 12, score: 90}
- </>

- <>
- // 一、借用父构造函数继承属性;
- // 1、父构造函数
- function Father(uname,age){
- // this 指向父构造函数的对象实例;
- this.uname = uname;
- this.age = age;
- }
- // 二、借用原型对象继承父类型方法
- Father.prototype.money = function(){
- console.log(10);
- }
-
- // 2、子构造函数
- function Son(uname,age,score){
- // this 指向子构造函数的实例对象;
- Father.call(this,uname,age);//调用父构造函数,把父构造函数中的this改为子构造函数中的this;
- this.score = score;
- }
- //这样直接赋值会有问题,如果修改了子原型对象,父原型对象也跟着修改了;
- //Son.prototype = Father.prototype;
- // 正确做法
- Son.prototype = new Father();
- // 如果利用对象的形式修改了原型对象,别忘了利用constructor指回原来的构造函数;
- Son.prototype.constructor = Son;
- Son.prototype.exam = function(){// 这个是子构造函数专门的方法
- console.log('考试');
- }
-
- var son = new Son('刘德华',12,90);
- console.log(son);//Son {uname: '刘德华', age: 12, score: 90}
- console.log(Father.prototype);
- console.log(Son.prototype.constructor);
- </>

call
方法的作用this
指向;fun.call(thisArg,arg1,arg2,...)
thisArg
:当前调用函数this
的指向对象;arg1,arg2
:传递的其他参数;- <>
- // call()
- function fn(x, y) {
- console.log('1111');
- console.log(this);//Window {window: Window, self: Window, document: document, name: '', location: Location, …}
- console.log(x + y);//3
- }
- var o = {
- name: 'andy'
- };
- //fn();
-
- // 1、call() 可以调用函数;
- fn.call();
-
- // 2、call() 可以改变这个函数的this指向;
- fn.call(o, 1, 2);//让this指向o这个对象;(o后面可以写需要传递的参数,如此处:1传给了x,2传给了y)
- </>

ES6
类的本质function
;prototype
属性上;__proto__
指向类的prototype
原型对象;ES6
的类它的绝大部分功能,ES5
都可以做到,新的class
写法只是让对象原型的写法更加清晰、更像面向对象编辑的语法而已;ES6
的类其实就是语法糖;- <>
- // 1、ES6之前,通过 构造函数 + 原型 实现面向对象 编程;
- /*
- 构造函数的特点:
- 1、构造函数有原型对象prototype;
- 2、构造函数原型对象prototype里面有constructor,指向构造函数本身;
- 3、构造函数可以通过原型对象添加方法;
- 4、构造函数创建的实例对象有__proto__原型 指向 构造函数的原型对象;
- */
-
- // 2、ES6通过 类 实现面向对象编程;
- class Star{
-
- }
- console.log(typeof Star);//function
- // 1、类的本质其实还是一个函数,我们也可以简单的认为,类就是构造函数的另外一种写法;
- // (1)、类有原型对象prototype;
- console.log(Star.prototype);
- // (2)、类原型对象prototype里面有constructor,指向类本身;
- console.log(Star.prototype.constructor);
- // (3)、类可以通过原型对象添加方法;
- Star.prototype.sing = function(){
- console.log('唱歌');
- }
- var ldh = new Star();
- console.dir(ldh);
- // (4)、类创建的实例对象有__proto__原型 指向 类的原型对象;
- console.log(ldh.__proto__ === Star.prototype);//true
- </>

ES5
中的新增方法ES5
中给我们新增了一些方法,可以很方便的操作数组或者字符串,这些方法包括:数组方法、字符串方法、对象方法;forEach()
、map()
、filter()
、some()
、every()
;forEach()
方法array.forEach(function(currentValue,index,arr){})
currentValue
:数组当前项的值;index
:数组当前项的索引;arr
:数组对象本身;- <>
- // forEach() 迭代(遍历)数组;
- var arr = [1,2,3];
- var sum = 0;
- arr.forEach(function(value,index,array){
- console.log('数组元素' + value);
- console.log('数组元素的索引号' + index);
- console.log('数组本身' + array);
- sum +=value;//求和
- })
- console.log(sum);//6
- </>
filter()
方法array.filter(function(currentValue,index,arr){})
filter()
方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选数组;currentValue
:数组当前项的值;index
:数组当前项的索引;arr
:数组对象本身;- <>
- var arr = [23,40,1,14,39,99];
- var newArr = arr.filter(function(value,index,arr){
- // return value >= 20;//筛选出大于20的数;
- return value % 2 == 0;//筛选出偶数;
- })
- console.log(newArr);
- </>
some()
方法array.some(function(currentValue,index,arr){})
some()
方法用于检测数组中的元素是否满足指定条件,通俗点,查找数组中是否有满足条件的元素;true
,如果查找不到就返回false
;currentValue
:数组当前项的值;index
:数组当前项的索引;arr
:数组对象本身;- <>
- // some() 查找数组中是否有满足条件的元素;
- // 查找数组中是否有大于等于20的元素;
- var arr = [10,30,4];
- var flag = arr.some(function(value,index,arr){
- return value >= 20;
- })
- console.log(flag);//true
-
- // 查找数组中是否有包含pink的元素;
- var arr1 = ['pink','plue','red'];
- var flag1 = arr1.some(function(value,inex,arr){
- return value === 'pink';
- })
- console.log(flag1);//true
- /*
- 1、filter 是查找满足条件的元素,返回的是一个数组,而且是把所有满足条件的元素返回回来;
- 2、some 是查找满足条件的元素是否存在,返回的是一个布尔值,如果查找到第一个满足条件的元素就终止循环;
- */
- </>

- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- table {
- width: 400px;
- border: 1px solid #000;
- border-collapse: collapse;
- margin: 0 auto;
- }
-
- td,
- th {
- border: 1px solid #000;
- text-align: center;
- }
-
- input {
- width: 50px;
- }
-
- .search {
- width: 600px;
- margin: 20px auto;
- }
- </style>
- </head>
-
- <body>
- <div class="search">
- 按照价格查询:<input type="text" class="start"> - <input type="text" class="end">
- <button class="search-price">搜索</button>
- 按照商品名称查询:<input type="text" class="product">
- <button class="search-pro">查询</button>
- </div>
- <table>
- <thead>
- <tr>
- <th>id</th>
- <th>产品名称</th>
- <th>价格</th>
- </tr>
- </thead>
- <tbody>
- <!-- <tr>
- <td>1</td>
- <td>小米</td>
- <td>3999</td>
- </tr> -->
- </tbody>
- </table>
- <>
- var data = [
- {
- id: 1,
- pname: '小米',
- price: '299'
- },
- {
- id: 2,
- pname: '大米',
- price: '399'
- },
- {
- id: 3,
- pname: '中米',
- price: '499'
- }
- ]
- // 1、获取相应的元素;
- var tbody = document.querySelector('tbody');
- setData(data);
- // 2、把数据渲染到页面中;
- function setData(myData) {
- // 先清空原来tbody里面的数据;
- tbody.innerHTML = '';
- // 再渲染新的数据;
- myData.forEach(function (value, index, arr) {
- var tr = document.createElement('tr');
- tr.innerHTML = `<td>${value.id}</td><td>${value.pname}</td><td>${value.price}</td>`;
- tbody.appendChild(tr);
- })
- }
-
- // 3、根据价格查询商品(当我们点击了按钮,就可以根据我们的商品价格去筛选数组里面的对象);
- var start = document.querySelector('.start');
- var end = document.querySelector('.end');
- var searchPrice = document.querySelector('.search-price');
- searchPrice.addEventListener('click', function () {
- var newData = data.filter(function (value) {
- return value.price >= start.value && value.price <= end.value;
- })
- // console.log(newData);
- // 把筛选完之后的对象渲染到页面中;
- setData(newData);
- })
- // 4、根据商品名称查询;
- var product = document.querySelector('.product');
- var searchPro = document.querySelector('.search-pro');
- searchPro.addEventListener('click', function () {
- // var newDataByName = data.filter((item) => {
- // return item.pname === product.value;
- // })
- // console.log(newDataByName);//some方法返回的是布尔值;
- // setData(newDataByName);
-
- // 如果查询数组中唯一的元素,用some方法更合适,因为它找到这个元素,就不再进行循环,效率更高;
- var arr = [];
- var newDataByName = data.some(function (value) {
- if (value.pname === product.value) {
- // console.log(value);
- arr.push(value);
- return true;//return后面必须写true;
- };
- })
- setData(arr);
- })
- </>
- </body>
-
- </html>

some
和forEach
区别- <>
- var arr = ['red', 'green', 'blue', 'pink'];
- // 1、forEach迭代 遍历
- // arr.forEach(function (value) {
- // if (value == 'green') {
- // console.log('找到该元素了');
- // return true; // 在forEach里面 return true 不会终止迭代;
- // }
- // console.log(11);//打印了3次11,'red','blue', 'pink'各打印了一次;
- // })
-
- // 2、some 迭代 遍历(如果查询数组中唯一的元素,用some方法更合适);
- arr.some(function (value) {
- if (value == 'green') {
- console.log('找到该元素了');
- return true; // 在some里面 return true 就是终止遍历,效率更高;
- }
- console.log(11);//只打印了1次11,'red'打印的,找到'green'后就不再往下执行了;
- })
- </>

trim
方法去除字符串两侧空格trim()
方法会从一个字符串的两端删除空白字符;str.trim()
trim()
方法并不会影响原字符串本身,它返回的是一个新的字符串;- <body>
- <input type="text"><button>点击</button>
- <div></div>
- <>
- // trim方法去除字符串两侧空格
- var str = ' andy ';
- console.log(str);
- var str1 = str.trim();
- console.log(str1);
-
- var input = document.querySelector('input');
- var btn = document.querySelector('button');
- var div = document.querySelector('div');
- btn.addEventListener('click', function () {
- var str = input.value.trim();
- if (str === '') {
- alert('请输入内容');
- } else {
- div.innerHTML = str;
- }
- })
- </>
- </body>

Object.defineProperty
方法Object.defineProperty()
定义对象中新属性或修改原有的属性;Object.defineProperty(obj,prop,deor)
obj
:必需,目标对象;prop
:必需,需定义或修改的属性的名字;deor
:必需,目标属性所拥有的特性;deor
说明:以对象形式{}书写value
:设置属性的值,默认为undefined
;writable
:值是否可以重写。true | false
,默认为false
;enumerable
:目标属性是否可以被枚举(遍历)。true | false
,默认为false
;configurable
:目标属性是否可以被删除或是否可以再次修改特性。true | false
,默认为false
;- <>
- // Object.defineProperty() 定义新属性或修改原有的属性
- var obj = {
- id: 1,
- pname: "小米",
- price: 1999
- };
- // 1、以前的对象添加和修改属性的方式;
- // obj.num = 10000;
- // obj.price = 99;
- // console.log(obj);
-
- // 2、Object.defineProperty() 定义新属性或修改原有的属性
- Object.defineProperty(obj, 'num', {
- value: 9000
- });
- // console.log(obj);
-
- // 如果对象中原来就有该属性,则会修改原属性;如果对象中原来没有该属性,就添加该属性;
- Object.defineProperty(obj, 'price', {
- value: 9.9
- });
- // console.log(obj);
-
- Object.defineProperty(obj, 'id', {
- // 如果值为false,则不允许重写(不允许修改该属性值);
- writable: false,
- });
- obj.id = '999';
- // console.log(obj);
-
- Object.defineProperty(obj, 'address', {
- value: '南京',
- // 如果值为false,则不允许重写(不允许修改该属性值);
- writable: false,
- // enumerable 如果值为false,则不允许遍历,默认的值是 false;
- enumerable: false,
- // configurable 如果为false则不允许删除某个属性,并且不允许再次修改第三个参数里面的【特性】;
- configurable: false,
- });
- console.log(Object.keys(obj));
- delete obj.address // 删除对象中的某个属性;
- </>

function
关键字(命名函数);new Function()
(此处的Function()
是一个构造函数);var fn= new Function('参数1','参数2',...,'函数体');
Function
里面参数都必须是字符串格式;Function
的实例(对象);- <>
- // 函数的定义方式
- // 1、自定义函数(命名函数);
- function fn() { }
-
- // 2、函数表达式(匿名函数);
- var fun = function () { };
-
- // 3、利用 new Function('参数1','参数2','函数体');
- var f = new Function('console.log(123)');
- f();
-
- var t = new Function('a', 'b', 'console.log(a + b)');
- t(1, 2);
-
- // 4、所有函数都是 Function 的实例(对象);
- console.dir(f);
- // 函数也属于对象;
- console.log(f instanceof Object); // true // instanceof 用于检测前者是否属于后者;
- </>

- <>
- // 1、普通函数
- function fn() {
- console.log(111);
- }
- // fn(); 或 fn.call();
-
- // 2、对象的方法(把函数放到对象里面叫方法);
- var o = {
- sayHi: function () {
- console.log(2222);
- }
- }
- o.sayHi();
- // 3、构造函数
- function Star() { };
- new Star();// 产生一个新的实例对象;
- // 4、绑定事件函数
- btn.onClick = function () { };//点击了按钮就可以调用这个函数;
- // 5、定时器函数
- setInterval(function () { }, 1000);//这个函数是定时器自动1秒钟调用一次;
- // 6、立即执行函数(立即执行函数是自动调用);
- (function () {
- console.log(3333);
- })()
- </>

this
指向this
指向(call()
、apply()
、bind()
)this
的指向问题,常用的有call()
、apply()
、bind()
;call()
方法call()
方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的this
指向;fun.call(thisArg,arg1,arg2,...)
- <>
- // 改变函数内this指向,js提供了三种方法 call()、apply()、bind();
-
- // 1、call(),第一个可以调用函数,第二个可以改变函数内的this指向;
- var o = {
- name: 'andy'
- }
- function fn(a, b) {
- console.log(a);
- console.log(b);
- // console.log(this);
- console.log(a + b);
- }
- fn(); //this 指向 window;
- fn.call(o, 1, 6) // this 指向 o 对象;
- // call() 的主要作用可以实现继承;
- function Father(uname, age, sex) {
- this.uname = uname;
- this.age = age;
- this.sex = sex;
- }
- function Son(uname, age, sex) {
- Father.call(this, uname, age, sex)//调用Father函数,并将Father的this指向改为Son的this;
- }
- var son = new Son('刘德华', 18, '男');
- // console.log(son);
- </>

apply()
方法apply()
方法调用一个函数,简单理解为调用函数的方式,但是它可以改变函数的this
指向;fun.apply(thisArg,[argsArray])
thisArg
:在fun
函数运行时指定的this
值;argsArray
:传递的值,必须包含在数组里面;- <>
- // 2、apply() 应用、运用的意思
- var o = {
- name: 'andy',
- };
- function fn(arr) {
- console.log(this);
- console.log(arr); // pink(注意:打印出来的是一个字符串,不是数组)
- }
- fn();// this 指向 window;
- fn.apply(o, ['pink']); // this 指向 o ;
- // 1、也是调用函数,第二个可以改变函数内部的this指向;
- // 2、但是它的参数必须是数组形式的(伪数组);
- // 3、apply的主要应用:比如说我们可以利用apply借助于数学内置对象求最大值;
- // Math.max();
- var arr = [1, 33, 55, 99, 8];
- // var max = Math.max.apply(null, arr);// null表示不需要改变this指向;
- var max = Math.max.apply(Math, arr);//this指向方法max的调用者Math,所以写成 Math 比 null 合适;
- console.log(max);// 99
- </>

bind()
方法bind()
方法不会调用函数,但是能改变函数内部this
指向;fun.bind(thisArg,arg1,arg2,...)
thisArg
:在fun
函数运行时指定的this
值;arg1,arg2
:传递的其他参数;this
值和初始化参数改造的原函数拷贝;- <body>
- <button>点击</button>
- <button>点击</button>
- <button>点击</button>
- <>
- // bind 绑定 捆绑 的意思;
- // var o = {
- // name: 'andy'
- // };
- // function fn(a, b) {
- // console.log(a + b);
- // console.log(this);
- // }
- // var f = fn.bind(o, 4, 12);// 没调用函数,所以没有打印;而是返回一个函数
- // f();//调用返回的函数;
-
- // 1、不会调用原来的函数,可以改变原来函数内部的this指向;
- // 2、返回的是原函数改变this之后产生的新函数;
- // 3、如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向,此时用bind;
- // 4、bind()方法应用案例:我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮;
- var btn = document.querySelector('button');
- // btn.addEventListener('click', function () {
- // this.disabled = true;
- // // 方法一:用变量来保存this指向(需要开辟新的内存空间,浪费内存);
- // var that = this;
- // setInterval(function () {//定时器函数里面的this指向的是window;
- // that.disabled = false;
- // }, 3000)
- // })
-
- // btn.addEventListener('click', function () {
- // // 方法二:用bind更方便;
- // this.disabled = true;
- // // setInterval(function () {//定时器函数里面的this指向的是window;
- // // this.disabled = false;
- // // }.bind(btn), 3000)
- // setInterval(function () {//定时器函数里面的this指向的是window;
- // this.disabled = false;
- // }.bind(this), 3000)//这个this指向的是btn这个对象,用this可以防止后期btn改变或有多个button的情况;
- // })
-
- // 当有多个按钮时
- var btns = document.querySelectorAll('button');
- for (let i = 0; i < btns.length; i++) {
- btns[i].onclick = function () {
- this.disabled = true;
- setInterval(function () {
- this.disabled = false;
- }.bind(this), 1000)
- }
- }
- </>
- </body>

call()
apply()
bind()
总结this
指向;call()
和apply()
会调用函数,并且改变函数内部this
指向;call()
和apply()
传递的参数不一样,call()
传递参数arg1
、arg2
… ,apply()
必须是数组形式[arg]
;bind()
不会调用函数,可以改变函数内部this
指向;call()
经常做继承;apply()
经常跟数组有关系,比如借助于数学对象实现数组最大值最小值;bind()
不调用函数,但是还想改变this
指向,比如改变定时器内部this
指向;JavaScript
除了提供正常模式外,还提供了严格模式(strict mode
)。ES5
的严格模式是采用具有限制性JavaScript
变体的一种方式,即在严格的条件下运行JS代码。IE10
以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。JavaScript
语义做了一些更改;JavaScript
语法的一些不合理、不严谨之处,减少了一些怪异行为(例如变量不声明就不能使用);ECMAScript
的未来版本中可能会定义的一些语法,为未来新版本的JavaScript
做好铺垫。比如一些保留字如:class
enum
export
extends
import
super
不能做变量名;"use strict"
(或'use strict'
);- <>
- "use strict"
- console.log("这是严格模式")
- </>
有的基本是严格模式,有的脚本是正常模式,这样不利于文件合并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他脚本文件。
- <>
- (function(){
- "use strict"
- var num = 10;
- function fn(){}
- })();
- </>
"use strict"
;(或'use strict';
)声明放在函数体所有语句之前;- <>
- function fn(){
- //此时,只是给fn函数开启严格模式;
- 'use strict';
- //下面的代码按照严格模式执行;但是fun里面的函数按照普通模式执行;
- }
- function fun(){}
- </>
JavaScript
的语法和行为,都做了一些变化;var
命令声明,然后再使用;- <>
- 'use strict';
- // 1、严格模式下变量名必须先声明再使用;
- num = 10;
- console.log(num);// num is not defined
- </>
(2)、严禁删除已经申明的变量。例如:delete
语法是错误的;
- <>
- 'use strict';
- // 2、严格模式下不能删除已经声明好的变量;
- var num = 10;
- console.log(num);
- delete num; //Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
- </>
this
指向问题:this
指向window
对象;this
是undefined
;new
也可以调用,当普通函数调用,里面的this
指向全局对象;new
调用,this
会报错;new
实例化的构造函数指向创建的对象实例;- <>
- 'use strict';
- // 3、严格模式下,如果构造函数不加new调用,this会报错;
- function Star() {
- this.sex = '男';
- }
- Star();
- console.log(window.sex);//普通模式下可以打印出“男”;严格模式下报错07.开启严格模式.html:25 Uncaught TypeError: Cannot set properties of undefined (setting 'sex')
- // 严格模式下全局作用域中函数的`this`是`undefined`;
- </>
(6)、定时器this
还是指向window
;
(7)、事件、对象还是指向调用者;
JavaScript
会引入“块级作用域”(ES6中已引入)。为了与新版本接轨,不允许在非函数的代码块内声明函数;https://developer.mozilla.org/zh-CN/docs/Glossary/strict_mode
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- < src="../../jQuery/jquery.min.js"></>
- <style>
- div {
- width: 100px;
- height: 100px;
- background: pink;
- position: absolute;
- }
- </style>
- </head>
-
- <body>
- <div></div>
- <>
- // 高阶函数 - 函数可以作为参数传递;
- function fn(a, b, callback) {
- console.log(a + b);
- callback && callback();
- }
- fn(1, 2, function () {
- console.log('我是最后调用的');
- });
-
- // 让div移动一段距离再变色;
- $("div").animate({ left: 500 }, function () { $("div").css("backgroundColor", "purple") })
- </>
- </body>
-
- </html>

closure
):指有权访问另一个函数作用域中变量的函数。—JavaScript
高级程序设计- <>
- // 闭包:指有权访问另一个函数作用域中变量的函数;
- // 一个作用域可以访问另外一个函数的局部变量;
- // 我们 fn 外面的作用域可以访问 fn 内部的局部变量;
- // 闭包的主要作用:延伸了变量的作用范围;
- function fn() {
- var num = 10;
- // function fun() {
- // console.log(num);
- // }
- // fun();
- // return fun;
- return function () {
- console.log(num);
- }
- }
- var f = fn();
- f();
- // 类似于
- // var f = function fun() {
- // console.log(num);
- // }
- </>

li
打印当前索引号- <body>
- <ul class="nav">
- <li>榴莲</li>
- <li>臭豆腐</li>
- <li>鲱鱼罐头</li>
- <li>大猪蹄子</li>
- </ul>
- <>
- // 闭包案例:点击li输出当前li的索引号;
-
- // 1、我们可以利用动态添加属性的方法来做;
- var lis = document.querySelector('.nav').querySelectorAll('li');
- for (var i = 0; i < lis.length; i++) {//for循环是一个同步任务;(for循环里i++是最后一步)
- // 解决方法:利用动态添加属性的方法来做;
- lis[i].index = i;
- lis[i].onclick = function () {//function是一个异步任务,只有点击了才会去执行;而for循环是一个同步任务;
- console.log(i);//所以打印出来的全部都是4;
- console.log(this.index);//打印出来的是索引;
- }
- }
-
- // 2、利用闭包的方式得到当前小li的索引号;
- for (var i = 0; i < lis.length; i++) {
- // 利用for循环创建了4个立即执行函数;
- // 立即执行函数也称为小闭包,因为立即执行函数里面的任何一个函数都可以使用它的i这个变量;
- (function (i) {
- // console.log(i);
- lis[i].onclick = function () {
- console.log(i);//缺点:特别占用内存,容易造成内存泄漏;好处:延长了变量的作用范围;
- }
- })(i)
- }
- </>
- </body>

li
内容- <body>
- <ul class="nav">
- <li>榴莲</li>
- <li>臭豆腐</li>
- <li>鲱鱼罐头</li>
- <li>大猪蹄子</li>
- </ul>
- <>
- // 闭包应用:3秒钟之后,打印所有li元素的内容;
- var lis = document.querySelector('.nav').querySelectorAll('li');
- for (var i = 0; i < lis.length; i++) {
- (function (i) {
- setTimeout(function () {
- // 异步任务的3种情况:定时器中的回调函数、事件(点击事件、鼠标事件等)中的回调函数、ajax中的回调函数;
- console.log(lis[i].innerHTML);
- }, 3000)
- })(i)
- }
- </>
- </body>

- <body>
- <>
- /*
- 闭包应用:计算打车价格
- 打车起步价13(3公里内),之后每多一公里增加5块钱,用户输入公里数就可以计算打车价格;
- 如果有拥堵情况,总价格多收取10块钱拥堵费;
- */
- var car = (function () {
- var start = 13;//起步价
- var total = 0;//总价
- return {
- // 正常的总价
- price: function (n) {
- if (n <= 3) {
- total = start;
- } else {
- total = start + (n - 3) * 5
- }
- return total;
- },
- //拥堵之后的费用;
- yd: function (flag) {
- return flag ? total + 10 : total;
- }
- }
- })();
- console.log(car.price(5));
- console.log(car.yd(true));
- console.log(car.price(1));
- console.log(car.yd(false));
- </>
- </body>

- <>
- // 1、思考题一:
- // var name = "The Window";//在全局作用域下定义的属性是挂在window下的;
- // var object = {
- // name: "My Object",
- // getNameFunc: function () {
- // return function () {
- // return this.name;//此处相当于一个立即执行函数,所以此处的this指向的是window;
- // };
- // }
- // }//此题中没有产生局部变量,所以没有闭包的产生;
- // console.log(object.getNameFunc()());//The Window
- // 分析
- // var f = object.getNameFunc();
- // 类似于
- // var f = function () {
- // return this.name;
- // }
- // f();
- // function(){this}() // 立即执行函数里的this指向的是window;
-
- // 2、思考题二:
- var name = "The Window";
- var object = {
- name: "My Object",
- getNameFunc: function () {
- var that = this;//此处的this指向的是object;
- return function () {
- return that.name;//
- };
- }
- }
- console.log(object.getNameFunc()())//My Object,有闭包的产生;
- // 分析
- // var f = object.getNameFunc();
- // var f = function () {
- // return that.name;//
- // };
- // f();
- </>

return
嵌套函数就可以在全局环境访问该变量;stack overflow
),所以必须要加退出条件return
;- <>
- // 递归函数:函数内部自己调用自己,这个函数就是递归函数;
- var num = 1;
- function fn() {
- console.log('我要打印6句话');
- if (num === 6) {
- return;//递归里面必须加退出条件;
- }
- num++;
- fn();
- }
- fn()
- </>
- <>
- // 1、求1*2*3...*n 阶乘
- function fn(n) {
- if (n === 1) {
- return 1;
- }
- return n * fn(n - 1);
- }
- console.log(fn(3));
- </>
- <>
- // 利用递归函数求斐波那契数列(兔子序列)1、1、2、3、5、8、13、21...
- // 用户输入一个数字n就可以求出这个数字对应的兔子序列值;
- // 我们只需要知道用户输入的n的前面两项(n-1 )就可以计算出n对应的序列值;
- // 这种方法效率较低,输入的数值较大时直接卡死;
- function fb(n) {
- if (n === 1 || n === 2) {// 用户输入1或2时,序列值都是1;
- return 1;
- }
- return fb(n - 1) + fb(n - 2);
- }
- console.log(fb(1));
- // console.log(fb(6));
- </>
- <body>
- <>
- var data = [{
- id: 1,
- name: '家电',
- goods: [{
- id: 11,
- gname: '冰箱',
- goods: [{
- id: 111,
- gname: '美的'
- }, {
- id: 112,
- gname: '海尔'
- }]
- }, {
- id: 12,
- gname: '洗衣机'
- }]
- }, {
- id: 2,
- name: '服饰'
- }]
- // 我们想要做输入id号,就可以返回的数据对象;
- // 1、利用 forEach 去遍历里面的每一个对象;
- function getID(json, id) {
- var o = {};
- json.forEach(function (item) {
- // console.log(item); // 2个数组元素
- if (item.id == id) {
- // console.log(item);
- o = item;
- // 2、我们想要得到里层的数据 11 12 可以利用递归函数;
- // 里面应该有 goods 这个数组并且数组的长度不为0;
- } else if (item.goods && item.goods.length > 0) {
- o = getID(item.goods, id);
- }
- });
- return o;
- }
- console.log(getID(data, 1));
- console.log(getID(data, 2));
- console.log(getID(data, 11));
- console.log(getID(data, 12));
- console.log(getID(data, 111));
- </>
- </body>

Object.assign(target,...sources)
ES6
新增方法可以浅拷贝;- <>
- // 浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用;
- // 深拷贝拷贝多层,每一级别的数据都会拷贝;
- var obj = {
- id: 1,
- name: 'andy',
- msg: {
- age: 18
- }
- };
- var o = {};
- // for (var k in obj) {
- // // k 是属性名;obj[k] 是属性值;
- // o[k] = obj[k];
- // }
- // console.log(o);
- // o.msg.age = 90;
- // console.log(obj);
- console.log('--------------');
- Object.assign(o, obj);//浅拷贝的语法糖
- console.log(o);
-
- // 数组也属于Object
- var arr = [];
- console.log(arr instanceof Object); //true
- </>

Regular Expression
)是用于匹配字符串中字符组合的模式。在javaScript
中,正则表达式也是对象;javaScript
正则表达式完成表单验证;javaScript
中,可以通过两种方式创建一个正则表达式。RegExp
对象的构造函数创建var 变量名=new RegExp(/表达式/)
var 变量名=/表达式/
test
test()
正则对象方法,用于检测字符串是否符合该规则,该对象会返回true
或false
,其参数是测试字符串;regexObj.test(str)
/abc/
,也可以是简单和特殊字符的组合,比如:/ab*c/
。其中特殊字符也被称为【元字符】,在正则表达式中是具有特殊意义的专用符号,如:^
、$
、+
等;^
和$
在一起,表示必须是精确匹配;- <>
- // 边界符 ^ $
- var rg = /abc/; //正则表达式里面不需要加引号,不管是数字型还是字符串型;
- // /abc/只要包含有abc这个字符串返回的都是true;
- console.log(rg.test("abc"));//true
- console.log(rg.test("abcd"));//true
- console.log(rg.test("aabcd"));//true
-
- console.log("------------");
-
- var reg = /^abc/;//以abc开头;
- console.log(reg.test("abc"));//true
- console.log(reg.test("abcd"));//true
- console.log(reg.test("aabcd"));//false
-
- console.log("------------");
-
- var reg1 = /^abc$/; //精确匹配,要求必须是abc字符串才符合规范;即以abc开头,又以abc结尾;
-
- </>

[-]
方括号内部范围符-
[^]
方括号内部 取反符 ^
- <>
- // 字符类:[] 表示有一系列字符可供选择,只要匹配其中一个就可以了;
- var rg = /[abc]/;//只要包含有a 或者 包含有b 或者包含有c 都返回为true;
- console.log(rg.test('andy'));//字符串andy里面包含有a,所以打印结果为true;
-
- var reg = /^[abc]$/; //三选一 只有是a 或者是b 或者是c 这三个字母才返回true;
-
- var rg1 = /^[a-z]$/;//26个英文字母任何一个字母返回true;-表示的是a到z的范围;
-
- // 字符组合
- var reg2 = /^[a-zA-Z]$/;//在小写和大写的26个英文字母中任选一个都可以;
- var reg3 = /^[a-zA-Z0-9]$/;//小写和大写的26个英文字母、0-9的数字
- var reg4 = /^[a-zA-Z0-9_]$/;//小写和大写的26个英文字母、0-9的数字、_
-
- // 如果中括号里面有^,表示取反的意思,千万别和边界符^混淆;
- var reg5 = /^[^a-zA-Z0-9_-]$/;//第一个^是边界符,表示以它开头;第二个^表示取反,即不能包含26个大写和小写英文字母和_-,
-
- </>

- <>
- // 量词符:用来设定某个模式出现的次数;
- // 简单理解:就是让下面的a这个字符重复多少次;
- var reg = /^a$/;
-
- // * 相当于 >= 0,可以出现0次或者很多次;
- var reg1 = /^a*$/;
- console.log(reg1.test(''));//true
- console.log(reg1.test('aaaaaa'));//true
-
- // + 相当于 >= 1,可以出现1次或者很多次;
-
- // ? 相当于 1 || 0;
-
- // {3 } 就是重复3次;
- var reg2 = /^a{3}$/;
-
- // {3, } 大于等于3;
-
- // {3,16} 大于等于3 并且 小于等于16;
-
- </>

- //前面的模式可以重复6到16次;
- var reg=/^[a-zA-Z0-9_-]{6,16}/
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- span {
- color: #aaa;
- font-size: 14px;
- }
-
- .right {
- color: green;
- }
-
- .wrong {
- color: red;
- }
- </style>
- </head>
-
- <body>
- <!--
- 功能需求:
- 1、如果用户名输入合法,则后面提示信息为:用户名合法,并且颜色为绿色;
- 2、如果用户名输入不合法,则后面提示信息为:用户名不符合规范,并且颜色为红色;
- 分析:
- 1、用户名只能为英文字母、数字、下划线或者短横线组成,并且用户名长度为6-16位;
- 2、首先准备好这种正则表达式模式 /$[a-zA-Z0-9_-]{6,16}^/;
- 3、当表单失去焦点就开始验证;
- 4、如果符合正则规范,则让后面的span标签添加right类;
- 5、如果不符合正则规范,则让后面的span标签添加wrong类;
- -->
- <input type="text" class="uname"><span>请输入用户名</span>
- <>
- var reg = /^[a-zA-Z0-9_-]{6,16}$/;
- var uname = document.querySelector('.uname');
- var span = document.querySelector('span');
- uname.onblur = function () {
- if (reg.test(this.value)) {
- console.log('正确的');
- span.className = 'right';
- span.innerHTML = '用户名格式输入正确';
- } else {
- console.log('错误的');
- span.className = 'wrong';
- span.innerHTML = '用户名格式输入错误';
- }
- }
- </>
- </body>
-
- </html>

- <>
- // 中括号 字符集合。 匹配方括号中的任意字符;
- var reg = /^[abc]$/; // a也可以,b也可以,c也可以;
-
- // 大括号 量词符。 里面表示重复次数;
- var reg1 = /^abc{3}$/; //它只是让c重复3次;abccc
- console.log(reg1.test(abc));//false
- console.log(reg1.test(abcabcabc));//false
- console.log(reg1.test(abccc));//true
-
- // 小括号 表示优先级;
- var reg2 = /^(abc){3}$/;//把abc重复3次;
- </>
- <>
- // 座机号码验证:全国座机号码 两种格式:010-12345678 或者 0530-1234567
- // 正则里面的“或者”符号 |
- var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;
- var reg1 = /^\d{3,4}-\d{7,8}$/;
- </>
- window.onload = function () {
- var regtel = /^1[3|4|5|7|8]\d{9}$/; // 手机号码的正则表达式;
- var regqq = /^[1-9]\d{4,}$/; // QQ号1000;
- var regnc = /^[u4e00-\u9fa5]{2,8}$/;//昵称
- var regmsg = /^\d{6}$/;//短信验证码,由6位数字组成;
- var regpwd = /^[a-zA-Z0-9]{6,16}$/;//密码
-
- var tel = document.querySelector('#tel');
- var qq = document.querySelector('#qq');
- var nc = document.querySelector('#nc');
- var msg = document.querySelector('#msg');
- var pwd = document.querySelector('#pwd');
- var surepwd = document.querySelector('#surepwd');
-
- regexp(tel, regtel);//手机号码验证
- regexp(qq, regqq);//QQ号码验证
- regexp(nc, regnc);//昵称验证
- regexp(msg, regmsg);//短信验证码
- regexp(pwd, regpwd);//密码框验证
-
- // 表单验证的函数封装
- function regexp(ele, reg) {
- ele.onblur = function () {
- if (reg.test(this.value)) {
- console.log('正确的');
- this.nextElementSibling.className = 'success';//nextElementSibling下一个兄弟
- this.nextElementSibling.innerHTML = '<i class="success_icon"></i>恭喜你输入正确';
- } else {
- console.log('错误的');
- this.nextElementSibling.className = 'error';//nextElementSibling下一个兄弟
- this.nextElementSibling.innerHTML = '<i class="error_icon"></i>输入错误';
- }
- }
- }
- // 确认密码
- surepwd.onblur = function () {
- if (this.value === pwd.value) {
- this.nextElementSibling.className = 'success';//nextElementSibling下一个兄弟
- this.nextElementSibling.innerHTML = '<i class="success_icon"></i>恭喜你输入正确';
- } else {
- this.nextElementSibling.className = 'success';//nextElementSibling下一个兄弟
- this.nextElementSibling.innerHTML = '<i class="error_icon"></i>两次输入密码不一致';
- }
- }
- }

replace()
replace()
方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则表达式;stringObject.replace(regexp/substr,replacement)
/表达式/[switch]
switch
(也称为修饰符)按照什么样的模式来匹配,有三种值:g
:全局匹配;i
:忽略大小写;gi
:全局匹配 + 忽略大小写;- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- div {
- width: 100px;
- height: 50px;
- background: pink;
- }
- </style>
- </head>
-
- <body>
- <textarea name="" id="message" cols="30" rows="10"></textarea>
- <button>提交</button>
- <div></div>
- <>
- // 替换 replace()
- var str = 'andy和red';
- //var newStr = str.replace('andy', 'bady');//第一个参数是被替换掉的,第二个参数是替换为的;
- var newStr = str.replace(/andy/, 'bady');
- console.log(newStr);//bady和red
-
- var text = document.querySelector('textarea');
- var btn = document.querySelector('button');
- var div = document.querySelector('div');
- btn.onclick = function () {
- // 注意:replace() 只能替换第一个满足条件的字符串,需要替换掉的字符串出现多次,它也只替换第一个;
- // div.innerHTML = text.value.replace(/激情/, '**');
- div.innerHTML = text.value.replace(/激情|gay/g, '**');//替换所有的“激情”和“gay”两个敏感词;
- }
- </>
- </body>
-
- </html>

ES6
ES
的全称是ECMAScript
,它是由ECMA
国际标准化组织,制定的一项脚本语言的标准化规范。var
let
const
关键字- <>
- var arr = [];
- for (var i = 0; i < 2; i++) {//for循环里用 var 申明变量,是一个全局变量;
- arr[i] = function () {
- console.log(i);
- }
- }
- // arr[0] 和 arr[1] 是两个函数,下面两句代码是在调用数组中的函数;
- arr[0]();//2 函数执行时在自己的作用域中找不到i值,根据作用域链会到上级作用域中去查找;
- arr[1]();//2
- // 当循环条件为 0 和 1 时,进入循环体;当循环条件为2时才跳出循环体,开始执行循环体后面的代码;
- // 注意:当i=0 和 i=1时,函数并没有执行;
- // 此题的关键点在于:变量i是全局的,函数执行时输出的都是全局作用域下的i值;
- // 当i=0 和i=1 时,arr数组中有两个值,这两个值都是 function () {console.log(i);}
- </>
- <>
- let arr = [];
- for (let i = 0; i < 2; i++) {
- arr[i] = function () {
- console.log(i);
- }
- }
- // arr[0] 和 arr[1] 是两个函数,下面两句代码是在调用数组中的函数;
- arr[0]();//0
- arr[1]();//1
- // 此题的关键点在于:每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的;
- // 函数执行时,输出的是自己上一级(循环产生的块级作用域)作用域下的i值;
- </>
const
关键字ES6
中允许从数组中提取值,按照对应位置,对变量赋值。对象也可以实现解构;- <>
- // 数组解构允许我们按照一一对应的关系从数组中提取值,然后将值赋值给变量;
- let arr = [1, 2, 3]
- let [a, b, c, d, e] = arr;//a、b、c和arr中的1、2、3是一一对应的关系;
- console.log(a);//1
- console.log(b);//2
- console.log(c);//3
-
- // 如果解构不成功,变量的值为undefined;
- console.log(d);//undefined
- console.log(e);//undefined
- </>
- <>
- // 对象解构允许我们使用变量的名字匹配对象的属性;匹配成功,将对象的属性值赋值给变量;
- let person = { name: '张三', age: 20 };
-
- // let { name, age } = person;
- // console.log(name);//张三
- // console.log(age);//20
-
- let { name: myName } = person;//此处的name只是用来属性匹配;此处的myName才是真正的变量;
- console.log(myName);//张三
- </>
ES6
中新增的定义函数的方式;- ()=>{}
- const fn=()=>{} //通常将箭头函数赋值给一个变量;
- fn()//调用箭头函数
- <>
- // 普通函数写法;
- function sum(num1, num2) {
- return num1 + num2;
- }
- // 箭头函数写法
- const sum = (num1, num2) => {
- return num1 + num2
- };
- // 1、在箭头函数中,如果函数体中只有一句代码,并且代码的执行结果就是函数的返回值,函数体 大括号 和 return 可以省略;
- const sum = (num1, num2) => num1 + num2;
-
- // 2、如果形参只有一个,可以省略小括号;
- function fn(v) {
- return v;
- }
- const fn = v => v;
- </>

this
关键字this
关键字,箭头函数中的this
,指向的是函数定义位置的上下文this
;即箭头函数被定义在哪,箭头函数中的this
就指向哪;- <>
- var obj = {
- age: 20,
- say: () => {
- alert(this.age);
- }
- }
- obj.say();//全局作用域下没有age属性,所以是undefined;
- </>
- <>
- function sum(first, ...args) {
- console.log(first);//10
- console.log(args);//[20,30]
- }
- sum(10, 20, 30);
-
- // 注意:在箭头函数中,使用不了arguments;
- const sum = (...args) => {
- let total = 0;
- args.forEach(item => total += item)
- return total;
- }
- console.log(sum(10, 20));//30
- console.log(sum(10, 20, 30));//60
- </>

- <>
- let students = ['王五', '张三', '李四'];
- let [s1, ...s2] = students;// s1 接收'王五';...s2 接收'张三', '李四',注意 s2 是一个数组;
- console.log(s1);//'王五'
- console.log(s2);//['张三','李四']
- </>
Array
的扩展方法 console.log();
打印结果时,逗号会解析为 console.log();
里多个元素的分隔符;- <>
- let arr = [1, 2, 3];
- // ...arr --> "a","b","c"
- console.log(...arr);//1 2 3
- </>
Array.from()
- <>
- // 扩展运算符
- // let arr = [1, 2, 3];
- // ...arr --> "a","b","c"
- // console.log(...arr);//1 2 3
-
- // 扩展运算符应用
-
- // 1、用于 合并数组;
- // 合并数组方法1:
- let arr1 = [1, 2, 3];
- let arr2 = [4, 5, 6];
- // ...arr1 //1,2,3
- //...arr2 //4,5,6
- // let arr3 = [...arr1, ...arr2]
- // console.log(arr3);//[1, 2, 3, 4, 5, 6]
-
- // 合并数组方法2:
- arr1.push(...arr2);
- console.log(arr1); //[1, 2, 3, 4, 5, 6]
-
- // 2、将 类、数组 或者 可遍历对象转换为真正的数组;
- let oDivs = document.getElementsByTagName('div');
- oDivs = [...oDivs];
- // Array.from 方法(将伪数组转换为真正的数组);
- var arrayLike = {
- "0": "张三",
- "1": "李四",
- "2": "王五",
- "length": 3
- }
- var ary = Array.from(arrayLike);
- console.log(ary);//['张三', '李四', '王五']
- </>

map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组;- // Array.from 还可以接收第二个参数,第二个参数是一个函数,对数组中的元素进行加工处理,数组中有多少个元素,该函数就会被调用多少次;形参item代表当前要处理的那个值;
- let arrayLike = {
- "0": 1,
- "1": 2,
- "length": 2
- }
- let newAry = Array.from(arrayLike, item => item * 2);
- console.log(newAry);//[2, 4]
Array.find()
方法undefined
;- <>
- let ary = [{
- id: 1,
- name: '张三'
- }, {
- id: 2,
- name: '李四'
- }];
- let target = ary.find((item, index) => item.id == 2);
- console.log(target);//{id: 2, name: '李四'}
- </>
Array.findIndex()
方法- <>
- let arr = [1, 5, 10, 15];
- let index = arr.findIndex((value, index) => value > 9);
- console.log(index);//2
- </>
Array.includes()
方法- [1,2,3].includes(2);//true
- [1,2,3].includes(5);//false
string
的扩展方法ES6
新增的创建字符串的方式,使用反引号定义;- let result={
- name:'zhangsan',
- age:20,
- sex:'男'
- };
- let html=`<div>
- <span>${result.name}</span>
- <span>${result.age}</span>
- <span>${result.sex}</span>
- </div>
- console.log(html);
- `
- const sayHello = function () {
- return '哈哈哈哈哈哈';
- };
- let greet = `${sayHello()}aaaa`;
- console.log(greet);
startsWith()
和endsWidth()
startsWith()
:表示参数字符串是否在原字符串的头部,返回布尔值;endsWidth()
:表示参数字符串是否在原字符串的尾部,返回布尔值;repeat()
方法repeat()
方法表示将原字符串重复n次,返回一个新字符串;- 'x'.repeat(3);//'xxx'
- 'hello'.repeat(2);//'hellohello'
Set
数据结构ES6
提供了新的数据结构Set
。它类似于数组,但是成员的值都是唯一的,没有重复的值;Set
本身是一个构造函数,用来生成Set
数据结构;const s = new Set();
Set
函数可以接受一个数组作为参数,用来初始化;const set = new Set([1,2,3,4,4])
Set
数据结构做数组去重:- <>
- const s1 = new Set();
- console.log(s1.size);//0
-
- const s2 = new Set(['a', 'b']);
- console.log(s2.size);
-
- const s3 = new Set(['a', 'a', 'b', 'b']);
- console.log(s3);//Set(2) {'a', 'b'}
- console.log(s3.size);//2 Set会把重复的值给过滤掉;
- const arr = [...s3];
- console.log(arr);//['a', 'b']
- </>
Set
对象实例方法add(value)
:添加某个值,返回Set
结构本身;delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功;has(value)
:返回一个布尔值,表示该值是否为Set
的成员;clear()
:清除所有成员,没有返回值;- const s = new Set();
- s.add(1).add(2).add(3);
Set
Set
结构的实例与数组一样,也拥有forEach
方法,用于对每个成员执行某种操作,没有返回值;s.forEach(value=>console.log(value))
- const s = new Set(['a', 'b', 'c', 'a', 'a']);
- s.forEach(element => {
- console.log(element);//a b c
- });
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。