前端入门到熟悉day27

31 篇文章 0 订阅
31 篇文章 0 订阅

rest参数
(1) Rest 参数接受函数的多余参数,组成一个数组,放在形参的最后,形式如下:
function func(a, b, …theArgs){
// …
}
(2) Rest参数和arguments对象的区别:
rest参数只包括那些没有给出名称的参数,arguments包含所有参数
arguments 对象不是真正的数组,而rest 参数是数组实例,可以直接应用sort, map, forEach, pop等方法
arguments 对象拥有一些自己额外的功能
(3) 从 arguments 转向数组
Rest 参数简化了使用 arguments 获取多余参数的方法
// arguments 方法function func(a, b){
var args = Array.prototype.slice.call(arguments);
console.log(args)
}
func(1,2)
// Rest 方法function func(a, b, …args){
// …
}
注意,rest 参数之后不能再有其他参数(即,只能是最后一个参数),否则会报错
function func(a, …b, c) {
// …
}// Rest parameter must be last formal parameter
函数的 length 属性,不包括rest参数
(function(a) {}).length // 1
(function(…a) {}).length // 0
(function(a, b, …c)).length // 2
(4) Rest参数可以被结构(通俗一点,将rest参数的数据解析后一一对应)不要忘记参数用[]括起来,因为它是数组
function f(…[a, b, c]) {
return a + b + c;
}
f(1) //NaN 因为只传递一个值,其实需要三个值
f(1, 2, 3) // 6
f(1, 2, 3, 4) // 6 (第四值没有与之对应的变量名)
//"…" rest参数
//let [st0,st1,…stn] = set1;

function fn(a,…b){
console.log(b);
}
// fn(1,2,3,4,5);
let arr1 = [1,2,3];
let arr2 = [4,5,6];
// let arr3 = arr1+arr2;
// console.log(arr3);
arr4 = arr1.concat(arr2)
// console.log(arr4);
//数据叠加
let arr3 = […arr1,…arr2];
// console.log(arr3);
// 数组追加
arr2.push(…arr1);
console.log(arr2);

commonjs介绍以及使用
CommonJS规范
1、CommonJs规范的出发点:JS没有模块系统、标准库较少、缺乏包管理工具;为了让JS可以在任何地方运行,以达到Java、C#、PHP这些后台语言具备开发大型应用的能力;
2、在CommonJs规范中:
    一个文件就是一个模块,拥有单独的作用域;
    普通方式定义的变量、函数、对象都属于该模块内;
    通过require来加载模块;
    通过exports和modul.exports来暴露模块中的内容;
 3、所有代码都运行在模块作用域,不会污染全局作用域;模块可以多次加载,但只会在第一次加载的时候运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果;模块的加载顺序,按照代码的出现顺序是同步加载的;
 4、__dirname代表当前模块文件所在的文件夹路径,__filename代表当前模块文件所在的文件夹路径+文件名;
 5、require(同步加载)基本功能:读取并执行一个JS文件,然后返回该模块的exports对象,如果没有发现指定模块会报错;
 6、模块内的exports:为了方便,node为每个模块提供一个exports变量,其指向module.exports,相当于在模块头部加了这句话:var exports = module.exports,在对外输出时,可以给exports对象添加方法,PS:不能直接赋值(因为这样就切断了exports和module.exports的联系);
 7、npm root -g:查看npm全局包安装位置,建议在nvm目录下新建npm\node_modules目录,然后设置npm的全局包安装位置:npm config set prefix “”,然后将该路径添加到环境变量中;
 8、npm init -y:初始化一个package.json文件,加上-y就会默认生成该文件,无需一步一步填写;npm docs 包名:查看包的文档;npm install:安装package.json中dependencies属性中所有依赖的包
 9、由于npm的服务器是国外的,所以如果你没有和谐工具是下载不了的,这里推荐使用淘宝NPM镜像:http://npm.taobao.org/,与官方NPM的同步频率目前为10分钟一次;安装命令:npm install -g cnpm --registry=https://registry.npm.taobao.org,安装包:cnpm install 包名(其它命令基本一致);
 10、如果你不想下载cnpm,npm还提供了一个镜像源管理工具:npm install -g nrm,通过:nrm ls,查看镜像源列表 ,通过:npm use 镜像源,来切换;
 11、NPM的模块加载机制:
      如果require的是绝对路径文件,查找不会去遍历每个node_modules目录,其速度最快
  1).从module.paths数组中(由当前执行文件目录到磁盘根目录)取出第一个目录作为查找基准
  2).直接从目录中查找该文件,如果存在则结束查找,如果不存在则进行下一条查找
  3).尝试添加.js、.node、.json后缀之后查找,如果存在文件则结束查找,如果不存在则进行下一条查找
  4).尝试将require的参数作为一个包来进行查找,读取目录下的package.json文件,取得Main参数指定的文件
  5).尝试查找该文件,如果存在则结束查找,如果不存在则进行第3条查找
  6).如果继续失败,则取出module.paths数组中的下一目录作为基准查找,循环第1-5个步骤
  7).如果继续失败,循环第1-6个步骤,直到module.paths中的最后一个值
  8).如果继续失败,则抛出异常

module.exports.adder = function(num0,num1){
return num0+num1;
}
module.exports.subber = function(num0,num1){
return num0-num1;
}

//导入模块 import(es6) include
let mtd = require("./2.js");
console.log(mtd.adder(1,2));
console.log(mtd.subber(3,2));
node.js 刚出来的时候是用于跟jsp php asp去做服务器端的开发 3p
js的执行环境
node就是把谷歌的v8引擎抠了出来 才可以执行js
执行js的时候为啥能够使用多种多样的资源 因为用的是commonjs来管理我们的模块 npm包管理工具去远程下载各种各样的依赖
生成器函数

  1. 生成器
    本质就是迭代器.
    一个一个的创建对象
    创建生成器的方式:
  2. 生成器函数
  3. 通过生成器表达式来获取生成器
  4. 类型转换(看不到)
  5. 生成器函数 (重点)
    生成器函数中包含 yield , 返回数据和return差不多.
    return会立即结束这个函数的执行
    yield 可以分段的执行一个函数
    生成器函数在执行的时候返回生成器. 而不是直接执行此函数
    能向下执行的两个条件:
    next(), 执行到下一个yield
    send(), 执行到下一个yield, 给上一个yield位置传值
    所有的生成器都是迭代器都可以直接使用for循环
    都可以使用list()函数来获取到生成器内所有的数据
    生成器中记录的是代码而不是函数的运行
    def func():
    print("我的天哪 ")
    yield “宝宝”
    gen = func() # 创建生成器. 此时运行会把生成器函数中的代码记录在内存
    当执行到__next__(), 运行此空间中的代码, 运行到yield结束.
    优点: 节省内存, 生成器本身就是代码. 几乎不占用内存
    特点: 惰性机制, 只能向前. 不能反复
    各种推导式 (诡异)
     列表推导式: 通过一行来构建你要的列表,列表推导式代码简单,但是出现错误后很难排查.[结果 for循环 if]
    集合推导式: 可以帮我们直接生成一个集合,并且可以去重{结果(k) for循环 if}
    字典推导式: 可以帮我们生成一个字典,例如需要将一个字典的key和value互换时用这个就很方便{结果(k:v) for循环 if}
    但是就没有元组推导式.(估计是因为元组不可变的缘故)

4.生成器表达式 (重点)
生成器表达式和列标推导式语法基本上是一致的,只要把[]换为()
(结果 for循环 if)
//生成器函数 Generator 异步的思想

//语法 function* fn(…; yield …? 外部调用 next();
function* 吃鸡(){
console.log(new Date());
console.log(“今晚准备吃鸡”);
yield ‘吃鸡第一步,买好鸡蛋’;
console.log(new Date());
console.log(“step2:孵化小鸡”);
yield ‘吃鸡第三步,养大小鸡’;
console.log(new Date());
console.log(“step3:小鸡长大”);
yield ‘吃鸡第四步,杀鸡’;
console.log(new Date());
console.log(“step4:准备炒鸡”);
yield ‘吃鸡第五步, 吃鸡’;
console.log(new Date());
console.log(“step5:吃鸡 the end”);
}
let cj = 吃鸡();
// cj.next();
// cj.next();
// cj.next();
// cj.next();
// cj.next();
let plan = [1000,2000,1500,3000];
let index=0;
function 今晚吃鸡(){
//异步执行
cj.next();
if(index<plan.length){
setTimeout(今晚吃鸡,plan[index++])
}
}
今晚吃鸡();
console.log(“大吉大利 主程序结束”)

//生成器函数的例子 斐波那契数列
function* Fibonacci(){
let posi0=0;
let posi1= 1;

while(true){
yield posi0;
//使用解构交换数据
// 0 1 1 1
[posi0,posi1]=[posi1,posi0+posi1]
// 1 1 1 2
// 1 2 2 3
}
}
let f = Fibonacci();
for(let index = 0;index<10;index++){
console.log(f.next().value);
}

箭头函数没有this
箭头函数的this绑定看的是this所在的函数定义在哪个对象下,绑定到哪个对象则this就指向哪个对象
如果有对象嵌套的情况,则this绑定到最近的一层对象上
ES6中定义的时候绑定this的具体含义,应该继承的是父执行上下文里面的this,切忌是父执行上下文!!!这样就很多箭头函数中的指向不明确就迎刃而解了。
注意:简单对象(非函数)是没有执行上下文的!
深入理解箭头函数中的this
箭头函数中,this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。
//es6中的拉姆达表达式:箭头函数
//匿名函数
let mth= function(){
//console.log(“execute1”);
}
mth();

(function(){
//console.log(“execute2”)
})();
let mth2=()=>{
// console.log(“lamuda OK”);
}
mth2();
// let mth3 = (a,b)=>{
// return ab;
// }
//默认只有一行:即返回值
let mth3 = (a,b)=>a
b;
let x3=mth3(3,4);
//console.log(x3=${x3});
let arrs = [1,2,3,4,5,6,7,8,9,10];
// arrs.forEach((v,i)=>{
// console.log(v);
// })
//arrs.forEach(v=>console.log(v));//简化代码
//箭头函数没有构造器,不可以创建对象实例,没有this
function Teacher(){
this.subject;
this.show=(times)=>{
this.name=‘mike’;//箭头函数没有this this实际上是指向Teacher()
for(let index=0;index<times;index++){
console.log(this.name+“教”+this.subject)
}
}
}
let ti= new Teacher();
ti.subject=“javascript”;
// console.log(ti.name);
//ti.show(3);
//console.log(ti.name);
//new ti.show();//没有构造器 不能new
// function Counter(){
// this.num = 0;
// this.timer = setInterval(function add(){
// console.log(new Date());
// console.log(this);
// },1000)
// }
// var b = new Counter();
// function Counter2() {
// this.num = 0;
// this.timer = setInterval(()=>{
// console.log(new Date());
// console.log(this);
// }, 2000);
// }
// var b = new Counter2();

promise介绍和使用
含义
Promise是异步编程的一种解决方案,用于一个异步操作的最终完成(或失败)及其结果值的表示,比传统的回调函数方案更加合理。
描述
Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。
一个 Promise有以下几种状态:
(1) pending: 意味着操作正在进行。
(2) fulfilled: 意味着操作成功。
(3) rejected: 意味着操作失败。
pending 状态的 Promise 对象可能触发fulfilled 状态并传递一个值给相应的状态处理方法,也可能触发失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected(可选参数),它们都是 Function 类型。
总结
then()方法、catch()方法是Promise()对象的原型方法,被Promise对象调用,返回值是一个Promise对象。
all()、race()、reject()、resolve()方法是Promise类的静态方法,被Promise类调用,返回值也是一个Promise对象。
使用new Promise((resolve, reject)=>{});的方式创建Promise对象时,如果构造函数中传递的不是function类型,则会报错。
new Promise((resolve, reject)=>{})的方式创建Promise对象时,调用resolve或reject函数时传递不同参数类型时该Promise对象的状态分析及其参数传递的不同情况分析。
p.then((result)=>{})或p.catch((err)=>{})方法调用时返回的Promise对象的状态及其参数传递的不同情况分析。
Promise.resolve(value)方法调用时返回的Promise对象的状态及其参数传递的不同情况分析。

//promise对象

// 三态:
// pending: 等待中,或者进行中,表示还没有得到结果
// resolved(Fulfilled): 已经完成,表示得到了我们想要的结果,可以继续往下执行
// rejected: 也表示得到结果,但是由于结果并非我们所愿,因此拒绝执行 error
// :提前预设好相应应的逻辑,达到三态的条件时自动的判断去执行(类似回调)
//做饭cook
function cook(){
console.log(“做饭了”)
let p = new Promise(function(resolve,reject){
//异步环境下随机状态
setTimeout(()=>{
let r = Math.random();
if(r>0.5){
console.log(“饭熟了!”)
resolve(“饭”);
}else{
console.log(“饭坏了,没法吃”);
reject(“error!”);
}
},2000)
});
return p;
}
//吃饭
function eat(food){
console.log(“吃”+food);
let p = new Promise(function(resolve){
//异步环境下随机状态
setTimeout(()=>{
resolve(“三个碗”)
},1000)
})
return p;
}
//洗碗
function wash(disk){
let p =new Promise(function(){
//异步环境下随机状态
setTimeout(()=>{
console.log(“洗”+disk)
},1000)
});
return p;
}
//调用 :使用promise对象
cook().then((fname)=>eat(fname))
.then((碟子)=>wash(碟子))
.catch((err)=>{
console.log(‘err:’+err)
})

promise : 承诺 解决回调地狱 回调链很难维护
ajax 异步的 a代表的是异步
$.get(取得商品类型的url,function(data){
if(error){
}else{
$.get(取得商品类型后取得商品列表url,function(data){
})
}
if(error){
}else{
$.get(取得商品类型后取得商品列表url,function(data){
})
}
if(error){
}else{
$.get(取得商品类型后取得商品列表url,function(data){
})
}
})
class关键字和extends继承
一、类(Class)
1.基本语法
JavaScript语言的传统方法是通过构造函数,定义并生成新对象。
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
构造函数的prototype属性,在ES6的“类”上面继续存在。事实上,类的所有方法都还是定义在类的prototype属性上面。
2.constructor方法
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

二、继承(Extends)
Class之间可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }
  toString() {
    return this.color + ’ ’ + super.toString(); // 调用父类的toString()
  }
}
上面代码中,constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。
三、原生构造函数继承
原生构造函数是指语言内置的构造函数,通常用来生成数据结构。ECMAScript的原生构造函数大致有下面这些。以前,这些原生构造函数是无法继承的。
Boolean() Number() String() Array() Date() Function() RegExp() Error() Object()
ES6允许继承原生构造函数定义子类,因为ES6是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承。下面是一个继承Array的例子。
class MyArray extends Array {
  constructor(…args) {
    super(…args);
  }
}
var arr = new MyArray();
arr[0] = 12;
arr.length // 1
arr.length = 0;
arr[0] // undefined
上面代码定义了一个MyArray类,继承了Array构造函数,因此就可以从MyArray生成数组的实例。这意味着,ES6可以自定义原生数据结构(比如Array、String等)的子类,这是ES5无法做到的。
四、Class的Generator方法
如果某个方法之前加上星号(*),就表示该方法是一个Generator函数。
class Foo {
  constructor(…args) {
    this.args = args;
  }
  * Symbol.iterator {
    for (let arg of this.args) {
      yield arg;
    }
  }
}
for (let x of new Foo(‘hello’, ‘world’)) {
  console.log(x);
}
// hello
// world
上面代码中,Foo类的Symbol.iterator方法前有一个星号,表示该方法是一个Generator函数。Symbol.iterator方法返回一个Foo类的默认遍历器,for…of循环会自动调用这个遍历器。
五、Class的静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo {
  static classMethod() {
    return ‘hello’;
  }
}
Foo.classMethod() // ‘hello’
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
上面代码中,Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。
父类的静态方法,可以被子类继承。
class Foo {
  static classMethod() {
    return ‘hello’;
  }
}
class Bar extends Foo {
}
Bar.classMethod(); // ‘hello’
上面代码中,父类Foo有一个静态方法,子类Bar可以调用这个方法。
//class关键字 定义一个类 constructor 构造器

class Student{
//构造器
constructor(stuname){
this.stuname = stuname;
}
showName(){
console.log(this.stuname);
}
}
let s1 = new Student(“Tom”);
// s1.showName();
//class -extends 继承
class QdStudent extends Student{
constructor(stuname,skill){
//父类的构造器先调用一下
super(stuname);
this.skill = skill;
}
//再去扩展一下方法
doWork(){
console.log(this.stuname+“擅长”+this.skill);
}
}
let s2 = new QdStudent(“Mike”,“p图”);
s2.doWork();
//module.exports common.js 引入 require
export{Student,QdStudent} //es6 引入import

import {QdStudent} from “./8.js”;
// /Nodejs 6.x版本还没有支持export 和import https://www.jb51.net/article/123927.htm
let s3 = new QdStudent(“Jack”,“吃鸡”);
s3.doWork();
//很多厂商都实现了 但是没通过 所以得babel解释器 才可以运行 三大框架内置了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值