javascript学习笔记(闭包)

什么是闭包?

当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前记法作用域之外执行。

function foo(){
    var a=2;
    function bar(){
        console.log(a);
    }
    bar();
}
foo();/2

这段代码是闭包吗?确切地说并不是。bar()引用a只是词法作用域的查找规则,而这些规则只是闭包的一部分。

function foo(){
    var a=2;
    function bar(){
        console.log();
    }
    return bar;
}
var baz=foo();
baz()/2--这就是闭包

bar()能访问foo()的内部作用域。然后我们将bar()函数本身当作一个值类型进行传递。把foo()赋值给baz,只是通过不同的标识符引用调用 了内部的函数bar().

function foo(){
    var a=2;
    function bar(){
        console.log(a);
    }
    baz(bar);
}
function baz(fn){
    fn();
}
foo();
var fn;
function foo(){
    var a=2;
    function bar(){
        console.log(a);
    }
    fn=bar;
}
function bar(){
    fn();
}
foo();
bar();

无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。

(250) 619-1089

一、类式继承 将第一个类的实例赋值给第二个类的原型叫类式继承.

function super(){
    this.supervalue=true;
}
super.prototype.getsupervalue=function(){
    return this.supervalue
}
function sub(){
    this.subvalue=false;
}
sub.prototype=new super();
sub.prototype.getsubvalue=function(){
    return this.subvalue
}

类式继承有两个缺点:

一、当父类中的共有属性为引用类型时,引用类型就会共用,其中一个实例修改引用类型的值,所有实例都会受到影响。

function superClass(){
    this.supervalue=true;
    this.books=['javascript','vue','node'];
}
superClass.prototype.getsupervalue=function(){
    return this.supervalue
}
function sub(){
    this.subvalue=false;
}
sub.prototype=new superClass();
sub.prototype.getsubvalue=function(){
    return this.subvalue
}
var person1=new sub();
var person2=new sub();
person1.books.push('css');
console.log(person1.books);/['javascript','vue','node','css']
console.log(person2.books);/['javascript','vue','node','css']

二、子类继承是靠基原型prototype对父类的实例化实现的,因此在创建父类时,是无法向父类传递参数的,因此在实例化父类的时候也无法对父类构造函数内的属性进行初始化.

vuex学习

STORE存储数据源,把数据分发给所有组件。

如果使用单一VUE,组件之间的数据传递相当麻烦,需要一层一层的传值。

添加组件修改了数据,STORE分发给需要的组件,更加清晰的管理数据。

VUEX中store.js文件

import Vue from 'vue'/引入vue
import Vuex from 'vuex'/引入vuex

Vue.use(Vuex)/vue使用use中间件使用vuex

export const store=new Vuex.Store({/实例vuex
    state:{/数据放在其中
        products:[
            {name:"马云",price:200},
            {name:"马化腾",price:140},
            {name:"马冬梅",price:20},
            {name:"马蓉",price:10}
        ]
    }
})

main.js中引入store并解构
import {store} from './store'
new Vue({
   store,
   render:h=>h(app)
}).$mount('#app')

组件中使用

计算属性中调用
export default {
  computed:{
      products:function(){
          return this.$store.state.products;/返回state中的products
      }
  }
}

store中的方法getters可以理解为store中的computed计算属性

getters:{
    saleProducts:function(state){
        var saleProducts=state.products.map(function(product){
            return{
                name:"**"+product.name+"**",
                price:product.price/2
            }
        })
        return saleProducts
    }
}

Mutations更像事件注册,当触发事件时,使用Mutations

mutations: {
  reducePrice:state=>{
      state.products.forEach(product=>{
          product.price-=1;
      })
  }
}
调用reducePrice方法
methods:{
    reducePrice:function(){
        this.$store.commit('reducePrice');/commit中的参数为调用mutations中的方法
    }
}

actions可以执行异步操作与传参

组件productOne

<button v-on:click="reducePrice(4)">商品降价</button>/点击按钮触发

methods:{
  reducePrice:function(amout){
     this.$store.dispatch('reducePrice',amout);/像amout参数传给actions中的reducePrice
   }
}

ations

actions: {
  reducePrice:(context,payload)=>{/context类似于methods中的this.$store,payload为传参
    setTimeout(function () {
        context.commit('reducePrice',payload);/触发mutations中的reducePrice方法,payload为传参
    },2000);/两秒后执行
  }
}

mutations

mutations: {
  reducePrice:(state,payload)=>{/payload为actions传来的参数
    state.products.forEach(product=>{
      product.price-=payload;
    })
  }
}

node.js笔记本五(express框架-ejs模板)

安装express,npm install express–save-node

在项目中实例化express对象

/引入express模块
var express=require('express');
var app=express();/实例化
app.get('/',function(req,res){/路由
  res.sendFile(__dirname+'/index.html');/路由到index页面
});
app.listen(3000);/监听3000端口

安装exj模板 npm install ejs –save-node

/引入express模块
var express=require('express');
/实例化express对象
var app=express();
/配置视图引擎
app.set('view engine','ejs');
/路由参数
app.get('/profile/:id',function (req,res) {
    res.render('profile',{name:"Hello world"});/寻找views下的profile.ejs文件,传参name:"Hello world"
})
/监听服务器端口号
app.listen(3333);

profile文件中

<h1>Webcome To <%= name %> page!</h1>/<%= name %>获取传参过来的name参数,显示在模块中

node.js笔记四(创建服务器与读写数据流)

创建服务器

var http=require('http');/引入http模块
var server=http.createServer(function(req,res){/创建服务
    res.writeHead(200,{"Content-type":"text/plain"});/向请求的客户端发送响应头.
    res.end("你请求到了");/返回数据
});
server.listen(3000,"127.0.0.1");/监听127.0.0.1地址的3000端口
console.log("server is running.....");

读取文件流

var fs=require('fs');
var myReadStream=fs.createReadStream('readMe.txt','utf8');/返回一个对象,基于EventEmitter事件
myReadStream.on('data',function (chunk) {/服务返回数据通过data方法
    console.log('正在接收一部份数据');
    console.log(chunk);
}); /读取文件放入缓存区,以流的形式返回

写入文件流

var fs=require('fs');
var myReadStream=fs.createReadStream('readMe.txt','utf8');
var myWriteStream=fs.createWriteStream('writeMe.txt');/返回一个对象
myReadStream.on('data',function (chunk) {
    console.log('正在接收一部份数据');
    myWriteStream.write(chunk);/使用write事件写入数据流
});

使用pipe事件,obj1.pipe(obj2);/调取obj1数据,写入obj2

var fs=require('fs');
var myReadStream=fs.createReadStream('readMe.txt','utf8');
var myWriteStream=fs.createWriteStream('writeMe2.txt');
myReadStream.pipe(myWriteStream);/将myReadStream中的数据写入myWriteSteam中

创建服务器将读取的文件流返回给客户端

var http=require('http');
var fs=require('fs');
var server=http.createServer(function(req,res){
    res.writeHead(200,{"Content-type":"text/plain"});
    var myReadStream=fs.createReadStream('readMe.txt','utf8');
    myReadStream.pipe(res);
})
server.listen(3000,"127.0.0.1");
console.log('server is running....');

node.js笔记三(创建和删除文件)

删除文件unlink(文件名,回调函数(err报错);

var fs=require('fs');/调用FS模块
fs.unlink('writeMe.txt',(err)=>{
    if(err)throw err;
    console.log("删除成功");
})/如果找不到要删除的文件抛出异常

同步创建文件夹mkdirSync(文件名);

var fs=require('fs');/调用FS模块
fs.mkdirSync('stuff');/创建stuff文件夹,若已有同名文件夹将报错

异步创建文件夹mkdir(文件名,回调函数(err报错));

var fs=require('fs');/调用FS模块
fs.mkdir('stuff',function () {
        if (err) throw err;
        console.log("创建成功");
})

同步删除文件夹rmdirSync(文件名);

var fs=require('fs');/调用FS模块
fs.rmdirSync('stuff');/删除stuff文件夹,若已有同名文件夹将报错

导步删除文件夹rmdir(文件名,回调函数);

fs.rmdir('stuff',(err)=>{
    if(err) throw err;
    console.log("删除成功");
});

异步创建一个stuff文件夹,然后读取readMe.txt文件,在stuff文件夹中写入一个writeMe.txt文件内容与readMe.txt文件相同

var fs=require('fs');z
fs.mkdir('stuff',function(){
     fs.readFile('readMe.txt','utf8',function(err,data){
        if(err)throw err;
        fs.writeFile('./stuff/writeMe.txt',data,(err)=>{
        if(err)throw err;
        })
     })
})

异步删除stuff文件夹,若文件夹中有文件,需要先删除文件再删除文件夹

fs.unlink('./stuff/writeMe.txt',(err)=>{
   fs.rmdir('stuff',(err)=>{
      if(err) throw err;
      console.log("删除成功");
   })
})

node.js笔记二(读取,写入事件)

同步读取事件 readFileSync(文件名,[option(编码格式)]);

创建readMe.txt文件内容为 温州是个好地方

var fs=require('fs');/调用FS模块
var readMe=fs.readFileSync('readMe.txt','utf8');/同步读取readMe.txt
console.log(readMe);/温州是个好地方

同步写入事件 writeFileSync(文件名,内容,[option(编码格式,默认为utf8)] );

var fs=require('fs');/调用FS模块
fs.writeFileSync('writeMe.txt',readMe);/writeMe.txt已存在则覆盖当前内容,否则创建writeMe.txt文件

异步读取事件readFile(文件名,[option(编码格式)],回调函数(err报错,data异步读取到的内容));

var fs=require('fs');/调用FS模块
fs.reFile('readMe.txt','utf8',(err,data)=>{
   if(err)throw err;/若报错,则抛出错误
   console.log(data);
})

异步写入事件writeFile(文件名,data[写入内容],[option(编码格式,默认为utf8)] ,回调函数(err报错);

var fs=require('fs');/调用FS模块
const data=('温州是个特别好地方');
fs.writeFile('writeMe3.txt',data,(err)=>{/writeMe.txt已存在则覆盖当前内容,否则创建writeMe.txt文件
   if(err) throw err;
})

2762786586

调用其他文件模块

hello.js为其他文件模块

var hello=function(){
    console.log('hello node.js');
}
module.exports=hello;

在main.js中调用hello模块,使用require方法,传入引入模块的相对路径,因为main.js和hello在同一个目录,所以我们用了当前目录.

var stuff=require('./hello.js');
stuff();/hello node.js

如果hello.js中有多个方法需要调用

var counter=function(arr){
    return '一共有' + arr.length +'个元素在数组中';
}
var adder=function(a,b){
    return `您需要计算的两个值的和为:${a+b}`;
}
var pi=3.142;
/*
console.log(counter(['Henry','Bucky','Emily']));*/
module.exports={
    counter:counter,
    adder:adder,
    pi:pi
}

在main.js中调用

var stuff=require('./stuff.js');
console.log(stuff.counter(['我是数组1','我是数组2']));/一共有2个元素在数组中

node.js中有一个events模块,该模块只提供了一个对象events.EventEmitter.他的核心就是事件触发与事件监听功能封装.

var events=require('events');
/创建eventEmitter;
var myEmitter=new events.EventEmitter();

myEmitter.on('someEvent',function(m){
        console.log(m);
});
/触发事件
myEmitter.emit('someEvent','实现事件并传递此参数到注册事件的回调函数中');/实现事件并传递此参数到注册事件的回调函数中