首页 文章 精选 留言 我的

精选列表

搜索[快速入门],共10000篇文章
优秀的个人博客,低调大师

快速了解 前端打包 webpack

一、介绍 (1)概念 webpack 用于编译 JavaScript 模块,是JavaScript 静态模块的打包工具。从 webpack v4.0.0 开始,可以不用引入一个配置文件。 (2)核心 1.入口(entry):指定webpack打包编译从哪个文件开始下手 入口起点(entry point)指示 webpack 使用哪个模块,作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。 webpack.config.js: module.exports = { entry: { main: './src' //打包入口,来指定一个入口起点(或多个入口起点,默认值为 ./src) }, entry: './src', //这个是上面的简写方式,是等价的 entry: { home: "./home.js", about: "./about.js", contact: "./contact.js" },//对象法指定多个入口,如果你想要多个依赖一起注入到一个模块,向 entry 属性传入「文件路径(file path)数组」。 entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])),//动态入口,当结合 output.library 选项时:如果传入数组,则只导出最后一项 }; 2.出口(output):指定webpack打包编译后的路径及文件名 output属性告诉 webpack 在哪里输出它所创建的bundles,以及如何命名这些文件。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。 webpack.config.js: const path = require('path'); module.exports = { entry: './src',//配置入口路径 output: { path: path.resolve(__dirname, 'dist'),//打包文件夹名,默认值为./dist filename: '[name].js'//入口文件名 } }; 3.loader(加载器):webpack识别不了的语言通过加载器来翻译 loader 用于转换某些类型的模块,webpack 自身只理解 JavaScript,loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块。loader 能够import导入任何类型的模块(如.css),是 webpack 特有的功能,其他打包工具有可能不支持。 webpack.config.js: const path = require('path'); const config = { output: { filename: 'my-first-webpack.bundle.js' }, module: { rules: [//在 webpack 配置中定义 loader 时,要定义在module.rules中,里面包含两个"必须属性":test和use { test: /\.txt$/, //test定义需要使用相应 loader 进行转换的某类文件 use: 'raw-loader' //use定义使用哪个 loader 进行转换 } ] } }; module.exports = config; 常见的例子: 4.插件(plugins):webpack完成不了的功能通过插件来完成 插件接口功能极其强大,可以用来处理各种各样的任务。通过require()使用插件,然后把它添加到plugins数组中。多数插件可以通过选项(option)自定义。 webpack.config.js: const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装 const webpack = require('webpack'); // 用于访问内置插件 const config = { module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] }, plugins: [ //在一个配置文件中因为不同目的而多次使用同一个插件,需要通过使用new操作符来创建它的一个实例 new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template: './src/index.html'}) ] }; module.exports = config; 5.模式(mode):通过模式确定是开发环境还是生产环境以便加载不同配置 module.exports = { mode: 'production'//通过选择development(开发)或production(生产),启用相应模式下的 webpack 内置的优化 }; 二、安装 (1)安装nodeJs webpack 配置是标准的 Node.js CommonJS 模块,在安装webpack之前,请确保安装了Node.js的最新版本,使用旧版本可能遇到各种问题(可能缺少 webpack 功能或者缺少相关 package 包)。 (2)安装webpack 1.本地安装 对于大多数项目,我们建议本地安装。这可以使我们在引入破坏式变更(breaking change)的依赖时,更容易分别升级项目。 npm install --save-dev webpack //安装最新版本 npm install --save-dev webpack@<version> //安装特定版本 操作如下: 2.全局安装 不推荐全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。 npm install --global webpack 3.最新体验版本 最新体验版本(可能仍然包含 bug)不应该用于生产环境 //直接从 webpack 的仓库中安装 npm install webpack@beta npm install webpack/webpack#<tagname/branchname> 4.安装 CLI 如果你使用 webpack 4+ 版本,你还需要安装 CLI。 npm install --save-dev webpack-cli //webpack-cli用于在命令行中运行 webpack 操作如下: 三、配置(configuration) webpack 的配置文件,是导出一个对象的 JavaScript 文件。webpack 需要传入一个配置对象(configuration object), 根据对象定义的属性进行解析,因此很少有 webpack 配置看起来很完全相同。可以通过两种方式(终端、Node.js)使用 webpack。 webpack 配置是标准的 Node.js CommonJS 模块,你可以: 通过require(...)导入其他文件,使用 npm 的工具函数 使用 JavaScript 控制流表达式 对常用值使用常量或变量 编写并执行函数来生成部分配置 请在合适的时机使用这些特性,虽然技术上可行,但应避免以下做法: 在使用 webpack 命令行接口(CLI)(应该编写自己的命令行接口(CLI),或使用--env)时,访问命令行接口(CLI)参数 导出不确定的值(调用 webpack 两次应该产生同样的输出文件) 编写很长的配置(应该将配置拆分为多个文件) 你需要从这份文档中收获最大的点,就是你的 webpack 配置,可以有很多种的格式和风格。但为了你和你的团队能够易于理解和维护,你们要始终采取同一种用法、格式和风格。 基本配置 webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装 const webpack = require('webpack'); //访问内置的插件 const path = require('path'); const config = { entry: './path/to/my/entry/file.js', output: { filename: 'my-first-webpack.bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.(js|jsx)$/, use: 'babel-loader' } ] }, plugins: [ new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template: './src/index.html'}) ] }; module.exports = config; 也可以 多个 Target:导出多个配置,或者,使用其他配置语言,webpack 接受以多种编程和数据语言编写的配置文件。

优秀的个人博客,低调大师

Hbase快速开始——shell操作

一. 介绍 HBase是一个分布式的、面向列的开源数据库,源于google的一篇论文《bigtable:一个结构化数据的分布式存储系统》。HBase是Google Bigtable的开源实现,它利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为协同服务。 HBase以表的形式存储数据。表有行和列组成。列划分为若干个列族/列簇(column family)。 如上图所示,key1, key2, key3是三条记录的唯一的row key值,column-family1, column-family2, column-family3是三个列族,每个列族下又包括几列。比如 column-family1这个列族下包括两列,名字是column1和column2。t1:abc,t2:gdxdf是由row key1和column-family1-column1唯一确定的一个单元cell。这个cell中有两个数据,abc和gdxdf。两个值的时间戳不一样,分别是t1,t2, hbase会返回最新时间的值给请求者。 二. 安装 下载HBase最新版本,放到合适的目录,比如/usr/local 或 /opt 之后解压 tar -zxvf hbase-x.y.z tar.gz 三. 命令行操作 进入解压后的目录,开启hbase,启动hbase shell bin/start-hbase.sh bin/hbase shell 输入 help 可以看到命令分组 部分命令清单 下边分组举例 general操作 查询服务器状态 status 查询hbase版本 version ddl操作 1. 创建一个表 create 'table1', 'tab1_id', 'tab1_add', 'tab1_info' 2. 列出所有的表 list 3. 获得表的描述 describe "table1" 4. 删除一个列族 disable alter enable disable 'table1' alter 'table1', {NAME=>'tab1_add', METHOD=>'delete'} enable 'table1' 5. 查看表是否存在 exists 'table2' 6. 判断表是否为‘enable’ is_enabled 'table1' 判断表是否为‘disable’ is_disabled 'table1' 7. 删除一个表 disable 'table1' drop 'table1' dml操作 1. 插入几条记录 1 2 3 4 5 6 put 'member' , 'scutshuxue' , 'info:age' , '24' put 'member' , 'scutshuxue' , 'info:birthday' , '1987-06-17' put 'member' , 'scutshuxue' , 'info:company' , 'alibaba' put 'member' , 'scutshuxue' , 'address:contry' , 'china' put 'member' , 'scutshuxue' , 'address:province' , 'zhejiang' put 'member' , 'scutshuxue' , 'address:city' , 'hangzhou' 2. 全表扫描 scan 3. 获得数据 get 3.1 获得一行的所有数据 3.2 获得某行,某列族的所有数据 3.3 获得某行,某列族,某列的所有数据 4. 更新一条记录 put(把scutshuxue年龄改为99) put 'member', 'scutshuxue', 'info:age', 99 5. 删除 delete、 deleteall 5.1 (删除行'scutshuxue', 列族为‘info' 中age的值 delete 'member', 'scutshuxue', 'info:age' 5.2 删除整行 deleteall 'member', 'scutshuxue' 6. 查询表中有多少行 count 'member' 7.给‘xiaoming’这个id增加'info:age'字段,并使用counter实现递增 incr 'member', 'xiaoming', 'info:age' 8. 将整个表清空 truncate 'member' tools操作 1. 创建一个表 四. 参考 http://smallwildpig.iteye.com/blog/1705718 本文转自jihite博客园博客,原文链接:http://www.cnblogs.com/kaituorensheng/p/3814925.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

HBase伪快速分页查询

之前有两个功能,都是查询历史数据的一个分页查询,系统刚上线的时候,没有太多的数据,就一直扔在mysql里面,后来里面数据上亿之后,就查不到了,而且数据还在以指数级增长方式上报,后来,这部分业务单独迁移到hbase集群去存放,之前页面的查询也改查hbase了。但是hbase对分页查询这种东西支持不好,如果按照以往查询mysql的思路,查询出一个总的count,再查询出这一页的数据,这种方式去查询hbase,那么如果你仔细去跟代码计算时间的话,你会发现hbase去查count,无论哪种方式,都会引起全表扫描,是非常慢的。整个页面加载出来,看了下响应事件,大概要45s,等的我都喝了两杯茶了。 so,我想了个比较伪的分页查询方法,去掉查询count操作,值查询一页数据: public Page<BatteryData> findBatterHisData(BatteryHisDto dto)throws Exception { Page<BatteryData> dataPage=new Page<BatteryData>(); List<BatteryData> dataList=new ArrayList<>(); int totalSize=0; Table table=runner.getTable(tableName); Scan dataScan=new Scan(); ResultScanner dataScanner=null; List<Filter> dataFilters = new ArrayList<Filter>(); if(StringUtils.isNotBlank(dto.getBatteryNo())){//电池组编号过滤 Filter filter=new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(dto.getBatteryNo()+"_")); dataFilters.add(filter); } Filter pageFilter=new PageFilter(dto.getPage()+dto.getPageSize()); dataFilters.add(pageFilter); FilterList dataFilterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, dataFilters); dataScan.setFilter(dataFilterList); dataScanner=table.getScanner(dataScan); dataList= rsh.handle(tableName,dataScanner); if(dataList==null || dataList.size()<1){ dataPage.setTotalCount(0); dataPage.setResult(null); return dataPage; } int startNo = dto.getPage(); int endNo=startNo+dto.getPageSize(); dataPage.setTotalCount(dto.getPage()+dto.getPageSize()+1); dataPage.setResult(dataList.subList(startNo,endNo)); table.close(); return dataPage; } 因为用户关注的,通常是前几页的数据,所有我每次查询的时候,返回总页数,都返回个随便的数(跟前端的分页表格配合,实际上,我的前端只提供了上下分页,哈哈),然后查询有限条的数据,通常hbase表都是上亿甚至是百亿的,所以,用户时不太可能通过只点击上一页下一页,这样点到我最后一页的,可以放心了。最多他点个几千页,也就手疼到不行了。这样下来,响应速度控制在800ms内,无压力。 PS,看到很多网友通过rowkey去做分页,具体思路是,每次记录下起始的rowkey和结束的rowkey,然后根据rowkey搜索,这样也是很快的,个人认为,也ok。

优秀的个人博客,低调大师

Centos 7 快速安装 Docker

安装 Docker [root@localhost~]# yum install docker 启动 docker 服务 [root@localhost~]# systemctl start docker.service [root@localhost~]# systemctl enable docker.service 安装 centos 镜像 [root@localhost~]# docker pull centos Using default tag: latest Trying to pull repository docker.io/library/centos ... latest: Pulling from docker.io/library/centos 6bbedd9b76a4: Downloading 2.531 MB/49.87 MB fc19d60a83f1: Download complete de413bb911fd: Download complete 2879a7ad3144: Download complete 668604fde02e: Download complete 668604fde02e: Pulling fs layer* 检查 centos 镜像安装状态 [root@localhost~]# docker images centos REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/centos latest 980e0e4c79ec 7 weeks ago 196.7 MB 运行一个新的容器 [root@localhost~]# docker run -i -t centos /bin/bash [root@bd1a482d44f5 /]# 参数解释 -i, --interactive Keep STDIN open even if not attached -t, --tty Allocate a pseudo-TTY PS:“[root@bd1a482d44f5 /]#” 这行出现证明已进入容器 退出容器 [root@localhost~]# exit exit 友情连接 Ubuntu上docker安装~~小鱼鱼

优秀的个人博客,低调大师

hive 结合mysql快速安装

系统使用centos7.1 官方下载hadoop,hive,jdk的安装包,解压在新建用户hive的目录下,安装mariadb-server(mysql-server) [hive@localhost ~]$ ll total 544900 drwxrwxr-x 9 hive hive 4096 Sep 10 07:31 apache-hive-2.1.0-bin -rw-rw-r-- 1 hive hive 149599799 Jun 21 01:26 apache-hive-2.1.0-bin.tar.gz drwxrwxr-x 9 hive hive 149 Sep 9 10:45 apache-tomcat-7.0.70 -rw-r--r-- 1 hive hive 8924465 Sep 9 10:29 apache-tomcat-7.0.70.tar.gz drwxr-xr-x 9 root root 139 Aug 18 01:49 hadoop-2.7.3 -rw-r--r-- 1 root root 214092195 Aug 25 19:25 hadoop-2.7.3.tar.gz lrwxrwxrwx 1 hive hive 12 Sep 9 08:28 hadoop-last -> hadoop-2.7.3 lrwxrwxrwx 1 hive hive 21 Sep 9 09:08 hive-last -> apache-hive-2.1.0-bin drwxr-xr-x 8 hive hive 4096 Jun 23 01:56 jdk1.8.0_102 -rw-r--r-- 1 root root 181435897 Sep 9 06:57 jdk-8u102-linux-x64.tar.gz drwxr-xr-x 4 hive hive 143 May 4 11:11 mysql-connector-java-5.1.39 -rw-r--r-- 1 hive hive 3899019 Sep 10 07:18 mysql-connector-java-5.1.39.tar.gz -rw-rw-r-- 1 hive hive 11183 Sep 9 10:18 wc.txt 修改用户的环境 [hive@localhost ~]$ cat .bash_profile # .bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environment and startup programs export JAVA_HOME=/home/hive/jdk1.8.0_102 export HADOOP_HOME=/home/hive/hadoop-last export HIVE_HOME=/home/hive/hive-last PATH=$PATH:$HOME/.local/bin:$HOME/bin:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HIVE_HOME/bin:$HIVE_HOME/conf export PATH 启动mysql数据库,为hadoop/hive添加一个用户 [root@localhost ~]# systemctl start mariadb [root@localhost ~]# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 3 Server version: 5.5.50-MariaDB MariaDB Server Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> CREATE USER 'hadoop'@'localhost' IDENTIFIED BY 'hadoop'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'hadoop'@'localhost' WITH GRANT OPTION; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> EXIT Bye MariaDB [(none)]> CREATE USER 'hive'@'localhost' IDENTIFIED BY 'hive'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'hive'@'localhost' WITH GRANT OPTION; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> exit Bye 进入$HIVE_HOME/conf,去掉以下三个文件的后辍.template -rw-r--r-- 1 hive hive 2378 Sep 10 06:24 hive-env.sh -rw-r--r-- 1 hive hive 2299 Jun 3 10:43 hive-exec-log4j2.properties -rw-r--r-- 1 hive hive 2950 Sep 10 06:25 hive-log4j2.properties 重命令hive-default.xml.template为hive-site.xml -rw-r--r-- 1 hive hive 225729 Sep 10 03:21 hive-site.xml 添加hive-env.sh两行 export HADOOP_HOME=/home/hive/hadoop-last export HIVE_CONF_DIR=/home/hive/hive-last/conf 修改hive-site.xml 默认hive.metastore.warehouse.dir是/user/hive/warehouse hive.exec.scratchdir是/tmp/hive 创建这个目录 如果是使用内置的derby存储metadata [hive@localhost hive-last]$ schematool -dbType derby -initSchema which: no hbase in (/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/hive/.local/bin:/home/hive/bin:/home/hive/jdk1.8.0_102/bin:/home/hive/hadoop-last/bin:/home/hive/hive-last/bin:/home/hive/hive-last/conf) SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/hive/apache-hive-2.1.0-bin/lib/log4j-slf4j-impl-2.4.1.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/hive/hadoop-2.7.3/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory] Metastore connection URL: jdbc:derby:;databaseName=metastore_db;create=true Metastore Connection Driver : org.apache.derby.jdbc.EmbeddedDriver Metastore connection User: APP Starting metastore schema initialization to 2.1.0 Initialization script hive-schema-2.1.0.derby.sql Initialization script completed schemaTool completed 修改 chmod a+rw /tmp/hive/ 下面修改为使用mysql hive-site.xml 480: javax.jdo.option.ConnectionPassword 481- hive 498: javax.jdo.option.ConnectionURL 499- jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true 932: javax.jdo.option.ConnectionDriverName 933- com.mysql.jdbc.Driver 960: javax.jdo.option.ConnectionUserName 961- hive 下载mysql-connector [hive@localhost mysql-connector-java-5.1.39]$ cp mysql-connector-java-5.1.39-bin.jar ~/hive-last/lib/ -v ‘mysql-connector-java-5.1.39-bin.jar’ -> ‘/home/hive/hive-last/lib/mysql-connector-java-5.1.39-bin.jar’ [hive@localhost hive-last]$ schematool -dbType mysql -initSchema which: no hbase in (/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/hive/.local/bin:/home/hive/bin:/home/hive/jdk1.8.0_102/bin:/home/hive/hadoop-last/bin:/home/hive/hive-last/bin:/home/hive/hive-last/conf) SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/hive/apache-hive-2.1.0-bin/lib/log4j-slf4j-impl-2.4.1.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/hive/hadoop-2.7.3/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory] Metastore connection URL: jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true Metastore Connection Driver : com.mysql.jdbc.Driver Metastore connection User: hive Starting metastore schema initialization to 2.1.0 Initialization script hive-schema-2.1.0.mysql.sql Initialization script completed schemaTool completed 修改hive-site.xml的system变量,解决变量无法识别的问题,使用绝对路径 :%s#${system:java.io.tmpdir}#/tmp/javaiotmp# :%s#${system:user.name}#hive#

优秀的个人博客,低调大师

ceph for openstack快速部署实施

for el6 即centos6 1,添加ceph 官方yum源 [root@ruiy ~]# cat /etc/yum.repos.d/ceph.repo[ceph-noarch]name=Ceph noarch packagesbaseurl=http://ceph.com/rpm-firefly/el6/noarchenabled=1gpgcheck=1type=rpm-mdgpgkey=https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc[root@ruiy ~]# 2,更新yum 源 yum update && sudo yum install ceph-deploy Installed: ceph-deploy.noarch 0:1.5.19-0Dependency Installed: python-argparse.noarch 0:1.2.1-2.el6Complete!

优秀的个人博客,低调大师

Jupyter Notebook入门指南

作者:京东科技隐私计算产品部 孙晓军 1. Jupyter Notebook介绍 图1 Jupter项目整体架构 [https://docs.jupyter.org/en/latest/projects/architecture/content-architecture.html] Jupyter Notebook是一套基于web的交互式开发环境。用户可以在线开发和分享包含代码和输出的交互式文档,支持实时代码,数学方程,可视化和 markdown等。用途包括:数据清理和转换,数值模拟,统计建模,机器学习等等。 Jupyter Notebook内部通过内核维护状态并运行代码片段,浏览器显示代码片段和其执行的结果。Jupyter Notebook提供了一个用户交互式的开发环境,用户可以通过执行一部分代码片段,并观察执行结果。这种交互式设计,使得Jupyter Notebook非常适合数据科学和机器学习的开发工作。 注意本文的代码和脚本,均基于Jupyter Notebook v6.5.2稳定版本。 2. Jupyter的工作方式 图2 Jupter Notebook工作方式 [https://docs.jupyter.org/en/latest/projects/architecture/content-architecture.html] Jupyter的主要工作单元是Jupyter Server和Kernel。其中Jupyter Server用来提供基于Web的界面和API服务,Kernel用来执行代码片段。浏览器通过Http和Websockets的方式和Jupyter Server进行交互,Jupyter Server和kernel之间,通过ZeroMQ进行数据通信。 Jupyter Server采用经典的MVC模式,使用了tornado作为web服务器,用来提供地址映射和控制器逻辑,使用jinja2来提供模板视图功能。 Jupyter Notebook(v6.5.2)项目的主要模块结构如下: 模块 说明 notebook Notebook功能模块。 terminal 终端模块。为Jupyter提供控制台交互能力。 view 文件可视化模块。比如pdf文件的显示。 tree 工作区目录树 nbconvert 格式转换模块,可以把Jupyter Notebook转换成html,pdf等格式 kernel Jupyter Notebook 内核 services Jupyter Notebook REST API模块 i18n Jupyter Notebook多语言资源 3. 安装Jupyter Notebook 前置条件 Python和pip 不同的Jupyter Notebook对Python有不同的版本要求。我们安装的最新的稳定版本v6.5.2的Jupyter Notebook,要求Python的最低版本为3.6。注意这个Python的版本,不同于内核的Python版本。对于Jupyter内核来说,支持的Python版本和Jupyter Notebook依赖的Python版本没有关系。 在Linux系统下安装Jupyter Notebook 使用pip安装Jupyter notebook非常简单。如果服务器同时拥有Python2和Python3的pip,注意需要使用pip3来替换命令中的pip。 # 更新pip pip install --upgrade pip # 安装jupyter pip install jupyter # 检查安装的jupyter jupyter --version //输出 notebook : 6.5.2 4. 配置和启动Jupyter Jupyter提供了大量的启动参数,用来配置Jupyter Server。我们可以在启动Jupyter服务时,通过命令行参数的方式配置当前启动的服务,但更普遍的方式是使用Jupyter的配置文件。 # 生成配置文件 jupyter notebook --generate-config // 默认生成的配置文件位置: /root/.jupyter/jupyter_notebook_config.py # 修改Jupyter配置文件... # 启动jupyter jupyter notebook Jupyter直接使用一个Python文件来配置Jupyter服务,所有的配置项均通过Python代码来完成。常用的配置项及其说明如下: 名称 默认值 说明 c.NotebookApp.allow_root False 为了安全,Jupyter默认不允许使用root用户启动。如果需要以root用户的身份启动Jupyter,需要开启此设定 c.NotebookApp.allow_origin '' 当需要Jupyter内嵌到iframe时,可以设置为“*“来避免跨origin的限制 c.NotebookApp.ip localhost 当需要通过外网地址来访问Jupyter服务时,需要设置一个有效的服务器IP地址。 c.NotebookApp.port 8888 Jupyter server对外服务端口 c.NotebookApp.notebook_dir / Jupyter的工作空间,默认可以访问服务器上当前用户的所有文件系统 c.NotebookApp.open_browser True 启动服务后是否立即通过浏览器打开服务地址 c.NotebookApp.default_url /tree Jupyter服务的默认地址 c.NotebookApp.extra_static_paths [] 扩展静态文件目录 c.NotebookApp.extra_template_paths [] 扩展模板文件目录 c.KernelSpecManager.allowed_kernelspecs set() 默认允许使用所有的kernel c.NotebookApp.nbserver_extensions {} 允许加载的Jupyter Server扩展 5. 使用Jupyter 5.1. 创建Notebook 启动Jupyter 后,在浏览器内输入 http://服务器地址:端口/,Jupyter会默认重定向到.default_url指定的工作区目录树地址,默认是工作区目录树的界面。 如果在访问的过程中,使用了默认的token作为其认证方式,那么在首次打开时,需要输入Jupyter Notebook的token值,这个值可以在启动Jupyter时的控制台输出中找到,或者使用Jupyter命令来查询 # 查询运行的jupyter notebook jupyter notebook list //返回结果中包含了http://x.x.x.x:8899?token=ABC 的信息,其中的ABC就是我们需要的token 图3 Jupter Notebook的默认工作区目录树页面 Jupyter Notebook通过Jupyter Server提供基于Web的平台无关的工作方式,这使得跨平台开发和协作,代码分享等能力变得比传统IDE更加容易。 在Jupyter 工作区管理界面,用户可以灵活地以类似文件系统的方式管理工作区的数据。可以创建文件和文件夹,编辑文件和文件夹,可以上传和下载文件。通过选择一个Jupyter内核,可以创建一个Notebook文件。 图4 通过Jupyter内核创建一个Notebook 5.2. 使用Notebook 使用Python3内核创建一个Notebook后,我们得到一个xxx.ipynb(IPython Notebook)文件。这个文件是一个json格式的文本文件,其中包含了我们在Notebook中编写的代码和文本内容,也包含了界面上没有显示的元数据信息。通过在工作区目录界面选择一个notebook文件,点击编辑,我们可以查看到ipynb文件的原始内容。 图5 ipynb文件的原始内容 我们可以像使用其它IDE类似的方式来使用Notebook,在使用Notebook上,我们主要关注下Jupyter内核和单元格。 内核是执行单元格代码的核心进程,不同的内核,决定了我们在单元格中能够编写哪些语言的代码,以及对应了指定的编程语言的哪个版本等信息。 单元格是整个Notebook的核心组成部分,我们编写的代码和文本,通过一些列Notebook单元格来组成。Notebook提供了Code,Markdown, Raw NBConvert, Heading四种类型的单元格。 •Code单元格。用来编写内核指定语言的程序代码 •Markdown单元格。使用Markdown编辑器的语法来编辑富文本 •Raw NBConvert单元格。原始的文本,不会被当作代码或markdown被解释执行 •Heading单元格。Heading是Mardown的一个子集,对应了Markdown中的标题编写语法 Jupyter Notebook使用了机器学习中检查点的概念,在我们修改Notebook的过程中,Jupyter会自动保存我们的修改,我们也可以通过【文件】->【保存】来手动保存检查点。检查点文件包含了我们编写的Notebook内容,以及执行代码单元格之后的输出。我们可以在工作空间的“.ipynb_checkpoints”文件夹下,找到这些检查点文件。 图6 使用Jupyter单元格来编写交互式代码 5.3. 分享Notebook 相较于使用传统的IDE编写的代码,基于Web服务的Jupyter Notebook在代码分享上拥有着天然的优势。 在Jupyter Notebook中,我们可以通过两种不同的方式分享我们创作的nootbook。 交互式Notebook文档 传统的技术文档或者说明书,通过静态的文本,配合图片和视频,来描述和讲解特定的技术或功能。有了Jupyter Notebook后,我们仍然可以使用Notebook来编写类似传统的技术文档。在此基础上,我们可以加入更生动的代码交互单元格,用户通过查看文档说明,并与文档中提供的代码进行互动,可以更生动地介绍产品中的功能和技术。每个Jupyter Notebook的ipynb文件,都对应了一个独立的访问地址: http://x.x.x.x:8899/notebooks/my_notebook.ipynb ,通过分享此文件的地址,其他用户可以方便地使用包含了富文本和可执行的代码的交互式Notebook文档。 离线Notebook文档 我们通过逐步执行文档中的所有单元格,得到一个包含了我们编写的说明和代码,以及代码执行的输出结果的完整文档。之后点击【文件】-> 【另存为】,选择一种合适的文件格式。我们可以把文档导出为一份静态文件,通过共享此静态文件,我们实现了Notebook文档的离线分享。 5.4. 魔法函数 Jupyter Notebook提供了一些列魔法函数来增强Jupyter Code单元格的功能,通过魔法函数,我们能够执行javascript脚本,html代码,运行另一个可执行程序等许多额外的功能。 我们可以在Jupyter代码单元格中使用 %lsmagic命令来查看所有的魔法函数,如果要阅读详细的魔法函数的使用说明,可以参考: https://ipython.readthedocs.io/en/stable/interactive/magics.html 魔法函数分为行魔法函数,单元格魔法函数和会话魔法函数。顾名思义,行魔法函数只对当前行起作用,而单元格魔法函数则作用于整个单元格,会话魔法函数则作用于整个会话期间。 一些常用的魔法函数: 指令 说明 %matplotlib 设置matplot绘图的显示模式 %%javascript 单元格内的代码被识别为javascript代码 %%html 单元格内的代码被识别为html代码 %run 执行外部脚本文件 %pwd 获取当前工作的目录位置(非工作空间目录位置) %writefile 以文件形式保存当前单元格代码 %timeit 获取本行代码的执行时间 %debug 激活调试模式 6. 管理Jupyter 6.1. 多语言 Jupyter Notebook使用i18n目录下的资源来进行多语言翻译。在Jupyter Notebook启动时,会加载i18n目录下的多语言资源。之后根据http请求指定的语言,为响应数据提供对应的多语言翻译。如果没有对应的翻译,则保留原始的多语言标签值(英文)。如果调整了多语言翻译,需要重新启动Jupyter Notebook才能使用新的语言包。 Jupyter Notebook的翻译资源主要分布在三个po文件中: •nbjs.po - js文件中的多语言数据 •nbui.po - UI界面中的多语言数据 •notebook.po - notebook中的多语言数据 原始的po文件,需要通过pybabel工具,把po文件编译成mo文件,之后部署在$notebook/i18n/${LANG}/LC_MESSAGES/目录下($notebook是notebook的安装目录),才能在Jupyter Notebook中作为多语言的资源包来使用。 # 使用pybabel编译多语言po文件 pybabel compile -D notebook -f -l ${LANG} -i ${LANG}/LC_MESSAGES/notebook.po -o ${LANG}/LC_MESSAGES/notebook.mo pybabel compile -D nbui -f -l ${LANG} -i ${LANG}/LC_MESSAGES/nbui.po -o ${LANG}/LC_MESSAGES/nbui.mo pybabel compile -D nbjs -f -l ${LANG} -i ${LANG}/LC_MESSAGES/nbjs.po -o ${LANG}/LC_MESSAGES/nbjs.mo 图7 使用了中文语言包后的中文Notebook界面 6.2. 内核管理 内核(kernel)是独立于jupyter服务和界面之外的用来运行Jupyter代码单元格的进程,Jupyter默认提供了ipykernel内核来支持Python开发语言。Jupyter社区提供了jupyterC, IJava,xeus-cling, xeus-sql等众多其它编程语言的内核,用来支持C/C++, Java, SQL等编程语言。 ipykernel默认使用系统环境下的Python来提供服务。我们可以使用ipykernel安装多个Python kernel来提供Python2.x, Python3.x等多个Python内核环境。 安装kernel后,kernel的信息被保存在kernel.json文件中,我们可以在 /usr/local/share/jupyter/kernels 目录,找到Jupyter安装的所有kernel以及对应的kernel.json文件。 kernel可以直接继承自安装kernel的Python指令,也可以使用Python虚拟环境。 # 1.直接继承自Python指令的kernel安装 # 安装ipykernel pip install ipykernel # 安装kernel python -m ipykernel install --name tensorflow2 --display-name "tensorflow2" # 2. 在Python虚拟环境下的kernel安装 # 激活虚拟环境 source activate myenv # 安装ipykernel pip install ipykernel # 安装kernel python -m ipykernel install --name myenv --display-name "Python3 (myenv)" 如果需要查看当前的kernel列表,以及删除已经安装的kernel,可以使用如下的Jupyter命令: # 查看已经安装的kernel列表 jupyter kernelspec list # 删除列表中指定的kernel jupyter kernelspec remove kernelname 6.3. REST API Jupyter提供了REST API接口来和Jupyter server进行交互。借助REST API的能力,我们可以以编程的方式和Jupyter Server进行交互,灵活地管理Jupyter Server。另外REST API为现代化的软件开发提供了一个优秀的能力:自动化。 借助Jupyter Notebook REST API,可以实现文件的上传和下载,检查点管理,会话管理,内核管理,终端管理等一些列管理能力。完整的Jupyter REST API接口列表可以参考: https://jupyter-server.readthedocs.io/en/latest/developers/rest-api.html 要使用REST API,需要在请求中携带认证信息。Jupyter支持直接把token作为query string的方式来认证,也可以使用标准的Http Authorization头信息来完成认证。使用Authorization头来认证的格式如下: Authrozation: token 527a9f1430ccfed995ebcf15517583a2547c2469bc3c47a6 图8 使用Postman来调用Jupyter REST API接口 6.4. 安全管理与多人协作 Jupyter提供了灵活强大的能力,用以支持在线的交互式文档和代码的编写。但Jupyter项目自身没有提供精细化的安全管理体系,用以支持多用户下灵活地使用Jupyter Notebook的功能。对于文件安全,Jupyter依赖于启动服务的linux用户,合理地配置启动Jupyter的用户的权限,才能保证使用Jupyter的用户,不会对系统或项目造成破坏。Jupyter工作空间的设定,仅起到了方便Jupyter使用者管理必要文件的易用性,不能阻挡用户访问和管理工作空间外的文件系统。另外,配合使用Python虚拟环境,可以防止Jupyter Notebook提供的 pip install ,pip uninstall功能,对现有项目环境造成破坏。 在多人协作方面,JupyterHub项目提供了多人协作Jupyter Notebook和Jupyter lab开发的能力。使用JupyterHub,不同职能的用户可以在自己独立的空间内进行Notebook的编写工作,不同用户间也可以方便地分享各自的Notebook。 7. 扩展Jupyter 7.1. 前端扩展 Jupyter Notebook前端扩展(front end extension)是使用Javascript语言编写的异步模块,可以用来绘制Jupyter界面的仪表盘,Notebook,工具栏等,。定义一个前端扩展必须要实现一个load_ipython_extension方法,当前端控件被加载时,Jupyter client会调用load_ipython_extension方法。 Jupyter Notebook前端扩展能力目前还不是一个稳定的版本,不保证代码能够向后兼容。Jupyter的JS API目前也没有官方的文档,需要通过源代码或者实际加载的JS来查看Jupyter前端脚本的成员和方法。 我们实现一个简单的前端扩展脚本,在jupyter前端的工具条中,添加一个自定义工具,当点击自定义工具时,弹出提示信息。 define([ 'base/js/namespace' ], function( Jupyter ) { function load_ipython_extension() { var handler = function () { alert('欢迎使用前端扩展!'); }; var action = { icon: 'fa-comment-o', help : '前端扩展', help_index : 'zz', handler : handler }; var prefix = 'my_extension'; var action_name = 'show-alert'; var full_action_name = Jupyter.actions.register(action, action_name, prefix); // returns 'my_extension:show-alert' Jupyter.toolbar.add_buttons_group([full_action_name]); } return { load_ipython_extension: load_ipython_extension }; }); 完前端扩展代码后,我们把脚本保存到main.js文件,放置在/opt/my_extension目录下。接下来我们使用jupyter nbextension工具来安装和启用前端扩展 # 安装前端扩展 jupyter nbextension install /opt/my_extension # 启用前端扩展 jupyter nbextension enable my_extension/main # 禁用前端扩展 jupyter nbextension disable my_extension/main # 查看前端扩展列表 jupyter nbextension list # 卸载前端扩展 jupyter nbextension uninstall my_extension 图9 在Notebook工具条中加入的前端扩展 7.2. 服务端扩展 Jupyter服务端扩展(server extension)是使用Python语言编写的模块,可以用来处理发送到Jupyter Server的Http请求。使用Jupyter服务端扩展,可以更改现有Jupyter请求的数据和行为,也可以为jupyter Server定义新的服务处理程序。 定义一个服务端扩展模块要实现一个load_jupyter_server_extension方法,其中包含一个类型为notebook.notebookapp.NotebookApp的参数serverapp,serverapp的详细属性和方法可以通过Jupyter Notebook源代码中的notebookapp.py文件来查看。当服务端扩展被加载时,Jupyter Server会调用load_jupyter_server_extension方法。在load_jupyter_server_extension方法中,我们可以通过调用serverapp的web_app属性的add_handlers方法来注册处理程序,用来处理特定的服务端请求。处理程序类需要继承自Jupyter的IPythonHandler类。在处理程序的方法中,可以使用Jupyter提供的@web.authenticated装饰器来为方法增加身份认证保护。 通过服务端扩展,还可以与前端扩展联动,实现一个功能丰富的Jupyter Notebook前端控件。 # 定义一个处理程序 from tornado import ( gen, web, ) from notebook.base.handlers import IPythonHandler class HelloWorldHandler(IPythonHandler): @web.authenticated @gen.coroutine def get(self): self.finish(f'Hello, world!') # 实现load_jupyter_server_extension方法并注册处理程序 def load_jupyter_server_extension(serverapp): handlers = [ ('/myextension/hello', HelloWorldHandler) ] serverapp.web_app.add_handlers('.*$', handlers) 完成服务端扩展代码后,我们把代码保存为__init__.py文件,要在Jupyter Notebook中使用处理程序,我们还需要进行服务端扩展的安装和启用。不同于前端扩展,服务端扩展不能直接使用指令来安装,需要我们手动编写安装程序。此外,Jupyter提供了自动启用服务端扩展和前端扩展的方法,需要我们在脚本的根目录提供启用扩展的配置文件。 jupyter-config/ ├── jupyter_notebook_config.d/ │ └── my_server_extension.json └── nbconfig/ └── notebook.d/ └── my_front_extension.json setup.py 加入了自动启用扩展的配置,我们的服务端扩展目录结构如下: hello-extension/ ├── __init__.py jupyter-config/ ├── jupyter_notebook_config.d/ └── hello_extension.json hello_extension.json文件的内容为: { "ServerApp": { "jpserver_extensions": { "hello_extension": true } } } 接下来我们通过安装程序,安装服务端扩展的信息保存在/root/.jupyter/jupyter_notebook_config.json文件中。在安装完成后,我们可以通过jupyter serverextesion工具来股那里服务端扩展 # 启用服务端扩展 jupyter serverextension enable hello_extension # 禁用服务端扩展 jupyter serverextension disable hello_extension # 服务端扩展直接卸载的方法,需要我们通过pip uninstall 卸载安装程序, # 再通过手工修改/root/.jupyter/jupyter_notebook_config.json文件删除扩展信息来完成卸载 图10 在浏览器中测试安装的服务端扩展程序 7.3. 界面定制 Jupyter没有提供标准的界面定制的能力,但我们可以手工调整jupyter生成的模板视图文件和样式文件,达到整条调整jupyter notebook的界面的能力。 Jupyter Notebook模板文件的位置为:$notebook/templates,样式和脚本定制推荐的方案是使用~/.jupyter/custom/custom.css和~/.jupyter/custom/custom.js文件。我们可以直接在此基础上对文件进行修改,还可以通过extra_template_paths和extra_static_paths来引入其它位置的模板和其它静态文件。 图11 通过直接调整模板文件加入的界面定制按钮 7.4. 小部件 小部件(Widgets)是Jupyter交互式可视化数据呈现部件。Jupyter Widgets同时包含了访问后端数据和前端呈现的能力,可以用于在Jupyter Notebook上生动地展示服务端的数据和数据变化。 在v6.5.2稳定版本上,我们目前只能使用系统提供的小部件,还不能开发自定义小部件。在Jupyter notebook7.x版本中,开始提供了小部件的自定义开发能力。 # 确保安装了ipywidgets和traitlets pip install --upgrade traitlets pip install --upgrade ipywidgets # 安装和启用小部件 jupyter nbextension install --py widgetsnbextension jupyter nbextension enable --py widgetsnbextension 在安装和启用了小部件后,我们可以在notebook中直接使用系统提供的小部件。 图12 在Notebook中使用小部件 完整的小部件列表和使用方式可以参考: https://ipywidgets.readthedocs.io/en/7.x/examples/Widget List.html 8. 总结 Jupyter Notebook以其丰富的功能,简单易用,强大的交互能力和扩展能力,成为数据科学和机器学习开发中的神器。目前,Jupyter Notebook支持超过40种编程语言,被应用于Google Colab, Kubeflow, 华为云,kaggle等多个知名项目中,大量机器学习和数据科学的论文中使用到了Jupyter。Jupyter在数据可视化,提升工作效率,改善用户体验和丰富文档功能方面显现了巨大的威力。除此之外,Jupyter还提供的灵活强大的扩展能力,更是为Jupyter的深层次使用提供了更广阔的想象空间。如果你还没有开始接触Jupyter,那么就从现在开始吧。

优秀的个人博客,低调大师

javascript 0基础入门

JavaScript基础 作者: 写代码的小鱼儿 Email:282505458@qq.com QQ:282505458 微信:15311464808 说明:本文档用于学习交流,可传播可分享,如有错误,请联系小鱼儿,感谢矫正与探讨 javascript简介 http://www.ecma-international.org/memento/TC39.htm 什么是JavaScript js 是一种 基于对象 的 弱类型 脚本语言; js 是一种 由浏览器解析的 解释型语言 js 区分大小写 轻量级解释型的程序设计语言 语言特点:动态,头等函数 执行环境:在宿主环境下执行(host environment),浏览器是最常见的 Javascript 宿主环境 作用 JavaScript 被用来改进设计、验证表单、检测浏览器、创建cookies,等等等等。 增加浏览器与用户的互动。 介绍 它最初由Netscape的Brendan Eich设计。JavaScript是甲骨文公司的注册商标。Ecma国际以JavaScript 为基础制定了ECMAScript标准。JavaScript也可以用于其他场合,如服务器端编程。完整的JavaScript 实现包含三个部分:ECMAScript,文档对象模型,浏览器对象模型。 Netscape在初将其脚本语言命名为LiveScript,后来Netscape在与Sun合作之后将其改名为 JavaScript。 JavaScript初受Java启发而开始设计的,目的之一就是“看上去像Java”,因此语法上有类 似之处,一些名称和命名规范也借自Java。但JavaScript的主要设计原则源自Self和Scheme。 JavaScript与Java名称上的近似,是当时Netscape为了营销考虑与Sun微系统达成协议的结果。为了取 得技术优势,微软推出了JScript来迎战JavaScript的脚本语言。为了互用性,Ecma国际(前身为欧洲计 算机制造商协会)创建了ECMA-262标准(ECMAScript)。两者都属于ECMAScript的实现。尽管 JavaScript作为给非程序人员的脚本语言,而非作为给程序人员的脚本语言来推广和宣传,但是 JavaScript具有非常丰富的特性。 发展初期,JavaScript的标准并未确定,同期有Netscape的JavaScript,微软的JScript和CEnvi的 ScriptEase三足鼎立。1997年,在ECMA(欧洲计算机制造商协会)的协调下,由Netscape、Sun、微 软、Borland组成的工作组确定统一标准:ECMA-262。 意义 JavaScript 发展到现在几乎无所不能。 网页特效 服务端开发(Node.js) 命令行工具(Node.js) 桌面程序(Electron) App(Cordova) 控制硬件-物联网(Ruff) 游戏开发(cocos2d-js) 什么是JavaScript JavaScript 被设计用来向 HTML 页面添加交互行为。 JavaScript 是一种直译式脚本语言(脚本语言是一种轻量级的编程语言),由浏览器直接解析。 JavaScript 由数行可执行计算机代码组成。 JavaScript 通常被直接嵌入 HTML 页面。 JavaScript 是一种解释性语言(就是说,代码执行不进行预编译)。 JavaScript是一种弱类型语言 JavaScript 区分大小写 Java 和 JavaScript 是相同的吗? 不同! 在概念和设计方面,Java 和 JavaScript 是两种完全不同的语言。 Java(由太阳微系统公司开发)很强大,同时也是更复杂的编程语言,就像同级别的 C 和 C++。 组成 ECMAScript – 标准,基本语法。JavaScript核心 ECMA 欧洲计算机制造联合会 网景:JavaScript 微软:JScript 定义了JavaScript的语法规范 JavaScript的核心,描述了语言的基本语法和数据类型,ECMAScript是一套标准,定义了一种语言的标 准与具体实现无关。 BOM – 浏览器对象模型 描述了与浏览器进行交互的方法和接口。,比如:弹出框、控制浏览器跳转、获取分辨率等 DOM – 文档对象模型 描述了处理网页内容的方法和接口 JavaScript 书写位置 (1)写在HTML标签中 < input type="button" value="提交" οnclick="alert('hello world')"> (2)写在script标签中 <head> <script> alert('Hello World!'); </script> </head> (3)写在外部js文件中,然后在页面使用标签引入 ​ 注意:引用外部 js文件的 script标签中不可以写 JavaScript代码 ​ 一般放在html文档的最后,body标签之前,这样能使浏览器更快的加载。 注意事项: script标签在页面中可以出现多对 script标签一般是放在body的标签的后,有的时候会在head标签中 在一对script的标签中有错误的js代码,那么该错误的代码后面的js代码不会执行 如果第一对的script标签中有错误,不会影响后面的script标签中的js代码执行 如果script标签是引入外部js文件的作用,那么这对标签中不要写任何的js代码,如果要写,重新 写一对script标签,里面写代码 script的标签中可以写属性, type="text/javascript"是标准写法或者写 language="JavaScript"都可以,也有可能出现这两个属性同时写的情况,但是,目前在我们的 html页面中,type和language都可以省略,原因:html是遵循h5的标准 在js中,回车换行就代表一个语句,后边的分号可以省略不写。但是在开发过程中,我们通常会将js代码压缩,压缩的时候会去掉回车,因此为了避免合并代码出错误,我们不会省略后面的分号。 (4)a 标签中使用(了解即可,不常用) < a href = "javascript:alert('aaa');" ></a> 变量声明 什么是变量 变量是计算机内存中存储数据的标识符,根据变量名称可以获取到内存中存储的数据 。 作用:操作数据 存储数据、 获取数据 声明变量 var 声明变量 var age;//声明变量 age = 1;//变量赋值 同时声明多个变量 var age, name, sex; age = 10; name = 'zs'; 同时声明多个变量并赋值 var age = 10, name = 'zs'; 变量的命名规范 规则 - 必须遵守的,不遵守会报错 由字母、数字、下划线、$符号组成, 不能以数字开头 不能是关键字和保留字,例如:for、while。 区分大小写 规范 - 建议遵守的,不遵守不会报错 变量名必须有意义 遵守驼峰命名法。 首字母小写,后面单词的首字母需要大写。例如:userName、 userPassword js声明变量都用var js中每一行代码结束加分号 面试题 交换两个变量的值: //方案一 利用临时变量 var a = 5; var b = 10; var t; t = a;//将a的值赋给临时变量t a = b;//将a 的值赋给b; b = t;//将t的值赋给b console.log(a); console.log(b); //方案二 让其中一个值变成与他们两个都有关系的值 var num1 = 1; var num2 = 3; num1 += num2;//num1赋值为两个数的和 num2 = num1 - num2;//和减去sum2得到sum1的值 num1 -= num2;//再把和减去sum2的值赋给sum1 console.log(num1); console.log(num2); //方案三 利用数组 var a1 = 2; var a2 = 4; a1 = [a1,a2];//将a1,a2的值作为数组的值赋给a1 a2 = a1[0]; a1 = a1[1]; console.log(a1); console.log(a2); //方案四 利用对象,原理同上 var o1 = 4; var o2 = 6; o1 = {o1:o2, o2:o1}; o2 = o1.o1; o1 = o1.o2; console.log(o1); console.log(o2); //方案五 原理还是数组 var aa = 40; var bb = 20; aa = [bb,bb = aa][0]; console.log(aa); console.log(bb); 输出方式 alert(‘弹框内容’); console.log(‘输出内容’); 控制台输出,F12 调出浏览器调试 document.write(‘内容’); 页面输出 prompt() 可以提交数据的弹框 注释 注释:解释代码含义 作用:解释说明,方便维护,利于团队合作 js注释 单行注释 : // 多行注释 : /* ... */ 一般用在代码段 html注释 css注释 /* … */ php注释 单行注释 // ​ 单行注释 # ​ 多行注释 /* … */ 注意:代码中要多加注释,否则不规范 注释的代码不会执行 数据类型 在编程语言中,能够表示并操作的值的类型叫做数据类型。 强类型语言:必须明确声明变量的数据类型的语言; 弱类型语言:不必须明确类型声明的语言。如js, 按简单复杂分 基本类型:number 、string 、boolean、 undefined 、null 复杂类型:object 、array 、date 、regexp 、function 、基本包装类型、单体内置对象(global、math) js 的数据类型有:六种 number、string、boolean、undefined、null、object Number类型 直接量就是可以在程序中直接使用的数据值。 数值字面量 数值的固定值的表示法 110 1024 60.5 进制 十进制 var num = 9; 进行算数计算时,八进制和十六进制表示的数值终都将被转换成十进制数值。 十六进制 var num = 0xA; 数字序列范围:09以及AF 八进制 var num1 = 07; // 对应十进制的7 var num2 = 019; // 对应十进制的19 var num3 = 08; // 对应十进制的8 数字序列范围:0~7 如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析 小数 数值范围 小值:Number.MIN_VALUE,这个值为: 5e-324 大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308 无穷大:Infinity 无穷小:-Infinity var n = 5e-324; // 科学计数法 5乘以10的-324次方 //不要用小数去验证小数 var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004 NaN not a number 的缩写,undefined 与数值运算得到的结果 它是一个特殊的值,不与任何数相等,包括它自己 var a; var b = 1; var c = a + b; console.log(NaN == NaN); console.log(isNaN(c)); 被0整除不会报错,只是简单的返回无穷大(infinity)或负无穷大(-infinity)。 0除以0无意义,结果为NAN。 console.log(Number.MAX_VALUE);//1.7976931348623157e+308 console.log(Number.MIN_VALUE);//5e-324 console.log(2 / 0);//Infinity 无穷大 isNaN 常用来判断变量是否是数值类型,true 表示不是数值 false表示是数值 var dd = 1; console.log(isNaN(dd)); string 字符串类型 由单引号或双引号包围 获取字符串的长度 变量.length var str = 'absfgfeh'; console.log(str.length); 转义字符/字符直面量 字面量 含义 \n 换行 \t 制表符,横向跳格 \b 空格 \r 回车 \f 换页符 \\ 反斜杠 ’ 单引号 " 双引号 \0nnn 八进制代码 nnn 表示的字符(n 是 0 到 7 中的一个八进制数字) \xnn 十六进制代码 nn 表示的字符(n 是 0 到 F 中的一个十六进制数字) \unnnn 十六进制代码 nnnn 表示的 Unicode 字符(n 是 0 到 F 中的一个十六进制数字) console.log('假期回来\\好开心啊'); console.log('假期回来"好开心"啊'); console.log("假期回来'好开心'啊"); console.log("假期回来'好\n开心'啊"); 字符串拼接 + console.log(11 + 11); console.log('hello' + ' world'); console.log('100' + '100'); console.log('11' + 11); console.log('male:' + true); 两边只要有一个是字符串,那么+就是字符串拼接功能 两边如果都是数字,那么就是算术功能。 Boolean类型 Boolean字面量: true和false,区分大小写 计算机内部存储:true为1,false为0 以下7种情况值可以转为false ,其他情况都会转成true。 数值0 空字符串 null undefined NaN false null null 用于对象 , 对象只有被定义才有可能为 null,否则为 undefined。 2.空类型 ,打印数据类型为对象 3.值只有一个:null 4.一个对象指向为空了,此时可以赋值为null 5.null只能手动赋值 var nul = null; console.log(nul); console.log(typeof nul); undefined undefined表示一个声明了没有赋值的变量 函数如果没有明确返回值,结果也是undefined 如果一个变量结果是undefined,和数字进行运算结果为NaN,不是一个数字,也没有意义 null 与 undefined 的区别: 共同点: 都表示值得空缺; 不包含任何属性和方法; 都只有自身一个值; 布尔类型都为假; 不同: undefined:系统级的、出乎意料的类似错误的值得空缺;预定义的全局变量 null:表示程序级的,正常的或意料之中的值得空缺。可作为参数传入函数 两者往往可以互换。“= =”认为两者是相等的,“===”认为是不等的,所以一般用严格相等来区别他们。 对象 object 与数组类似,同样是使用一个名字表示一组值。对象的每个值都是对象的一个属性。 对象可以看做是属性的无序集合,每个属性都是一个名/值对。 使用点号来获取属性。 语法结构: {propertyname:value,propertyname:value} var lennon = {name:John,year:1940,living:false} var obj = new Object; console.log(obj); console.log(typeof obj); 用法: create(创建)、set(设置)、query(查找)、delete(删除)、test(检测)和枚举属性。 获取变量的类型 typeof 两种使用方式: typeof 变量名 typeof(变量名) var age = 18; console.log(typeof age); // 'number' console.log(typeof(age)); instanceof 检测对象是否是某个函数的实例对象 object.prototype.toString.call() 检测对象的原型对象 数据类型转换 转换成数值类型 类型转换分为 显示转换:如转换函数Number() 、parseInt() 等等 隐式转换:指在计算或判断过程中自动转换的方式。如:“10” - 4 = 6 Number() 转换成数值类型,严格转换。有一个非数字符都不可转换 Number()可以把任意值转换成数值,如果要转换的字符串中有一个不是数值的字符,返回NaN console.log(Number(10));//10 console.log(Number(''));//0 console.log(Number(null));//0 console.log(Number(10.4));//10.4 console.log(Number('a10'));//NaN console.log(Number(3e5));//300000 console.log(Number('abd'));//NaN console.log(Number('123bd'));//NaN console.log(Number(true));//1 console.log(Number(false));//0 console.log(Number(NaN));//NaN console.log(Number(undefined));//NaN parseInt() 转换成整数。 只取整数部分,忽略小数部分(从第一个字符开始查找,找到非数字截止,并返回找到的数字) console.log(parseInt(10));//10 console.log(parseInt(10.4));//10 console.log(parseInt('a10'));//NaN,如果第一个字符不是数字或者符号就返回 NaN console.log(parseInt(3e5));//300000 console.log(parseInt('abd'));//NaN console.log(parseInt('123bd'));//123,如果第一个字符是数字会解析,直到遇到非数字结束 console.log(parseInt(NaN));//NaN console.log(parseInt(undefined));//NaN parseFloat() 把字符串转换成浮点数,即小数。 console.log(parseFloat(10));//10 console.log(parseFloat(10.4));//10.4 console.log(parseFloat('a10'));//NaN,如果第一个字符不是数字或者符号就返回 NaN console.log(parseFloat('0.1.0'));//0.1,会解析第一个. 遇到第二个.或者非数字结束 console.log(parseFloat(3e5));//300000 console.log(parseFloat('abd'));//NaN console.log(parseFloat('123bd'));//123,如果第一个字符是数字会解析,直到遇到非数字结束 console.log(parseFloat(NaN));//NaN console.log(parseFloat(undefined));//NaN parseFloat()和parseInt非常相似,不同之处在于 parseFloat会解析第一个. 遇到第二个.或者非数字结束 如果解析的内容里只有整数,解析成整数 + - 0运算 var str = '500'; console.log(+str); // 500 取正 console.log(-str); // -500 取负 console.log(str - 0);//500 转换成字符串类型 String():可以转所有字符 .toString():不能转无意义的字符,如null、undefined var num = 5; console.log(num.toString());//5 .toString 语法 console.log(*String*(num));//5 String 语法 拼接字符串方式 num + “”,当 + 两边一个操作符是字符串类型,一个操作符是其它类型的时候,会先把其它类型 转换成字符串再进行字符串拼接,返回字符串 转换成布尔类型 Boolean() 以下7种情况值可以转为false ,其他情况都会转成true。 整数0 浮点数0 空字符串 null undefined NaN false 注意与PHP区分:在PHP中字符串 ‘0’ ,空数组也被认为是false 运算符/操作符 算数运算符 + - * / % js支持的更复杂的运算: Math.pow(2, 53 ) // 2的53次幂 Math.round(.6) // 1; 四舍五入 Math.ceil(.6) // 1;向上求整 Math.floor(.6) // 0;向下求整 Math.abs(-5) // 5; 求绝对值 Math.max(x, y, z) // 返回最大值 Math.min(x, y, z) // 返回最小值 Math.random() // 生成一个大于等于0小于等于1的伪随机数? Math.PI // π:圆周率 Math.E // e:自然对数的底数 Math.sqrt(3) // 3的平方根 Math.pow(3 , 1/3) //3的立方根 Math.sin(0) // 三角函数,还有Math.cos()、Math.atan()等 Math.log(10) // 10的自然对数 Math.log(100)/Math.LN10 // 以10为底100的对数。 Math.log(512)/Math.LN2 // 以2为底512的对数 Math.exp(3) // e的三次幂 比较运算符/关系运算符 返回值为布尔值。 < > >= <= == != === !== //==与===的区别:==只进行值得比较,===类型和值同时相等,则相等 var result = '55' == 55; // true var result = '55' === 55; // false 值相等,类型不相等 var result = 55 === 55; // true 赋值运算符 又叫复合运算符。 = += -= *= /= %= var num = 0; num += 5; //相当于 num = num + 5; 逻辑运算符 返回值为布尔值。 && 逻辑与 两个操作数同时为true,结果为true,否则都是false || 逻辑或 两个操作数有一个为true,结果为true,否则为false ! 逻辑非 取反 从右向左执行 一元运算符 一元运算符:只有一个操作数的运算符。 ++ -- 主要是对其他操作数的影响不同,对其自身影响永远都是加一或减一 前置++ 先自增,再赋值 var num1 = 5; ++ num1; var num2 = 6; console.log(num1 + ++ num2);//13 后置++ 先赋值,再自增 var num1 = 5; num1 ++; var num2 = 6; console.log(num1 + num2 ++);//6+6=12 三元运算符 表达式1 ? 表达式2 : 表达式3 用法同 if 的双向条件语句,以下if条件语句: var age = 18; ​ if (age < 18) { ​ document.write('未成年'); ​ } else { ​ document.write('成年'); ​ } 可以写成: var age = 18; var res = age>= 18 ? '成年' : '未成年'; document.write(res); 运算符优先级 优先级从高到低 (1)括号 () 优先级最高; (2)一元运算符 ++ – ! (3)算数运算符 ,同数学运算。 先乘除求模(* / %),再加减(+ -); (4)关系运算符 > >= < <= (5)相等运算符 == != = == !== (6)逻辑运算符 先 && 后 || (7)赋值运算符 // 练习1: 4 >= 6 || '人' != '猫' && !(12 * 2 == 144) && true // true // 练习2: var num = 10; 5 == num / 2 && (2 + 2 * num).toString() === '22'//true 流程控制 流程控制的三种基本结构 顺序结构:从上到下,从左到右,从右向左 分支结构:单分支,双分支,多分支 循环结构:for循环,while循环,do…while循环 顺序结构 程序默认就是由上到下顺序执行的 。 分支结构 if语句 语法结构: //单分支结构 if (/* 条件表达式 */) { // 执行语句 } //双分支结构 与三元运算符等价 1 ?2 : 3; if (/* 条件表达式 */){ // 成立执行语句 } else { // 否则执行语句 } //多分支结构 if (/* 条件1 */){ // 成立执行语句 } else if (/* 条件2 */){ // 成立执行语句 } else if (/* 条件3 */){ // 成立执行语句 } else { // 后默认执行语句 } 注意: 条件必须放在if后的圆括号内; 小括号中的条件语句结果只能为布尔值,即true / false; 花括号内的语句必须在满足条件时执行。 最多只有一个区间被执行。 如果if语句中的花括号部分只包含一条语句,那么可以省略花括号,而且这条语句的全部内容可以写在一行。 switch语句 语法结构:严格模式 switch (expression) { case 常量1: 语句; break; case 常量2: 语句; break; case 常量3: 语句; break; … case 常量n: 语句; break; default: 语句; break; } 注意: break可以省略,如果省略,代码会继续执行下一个case switch 语句; 在比较值时使用的是全等操作符, 因此不会发生类型转换(例如,字符串’10’ 不等于数值 10); 声明的变量类型必须与case后的值的类型相同,否则不会执行。 全等操作,类型转换案例: //使用switch语句将输入的1—12值转换成对应的“本月有多少天” //prompt 为弹框,可以传递数据值 //prompt的结果为字符串类型,用switch时需要将其转为数值类型 var day = parseInt(prompt('请输入一个月份')); switch (day) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: document.write('这个月有31天'); break; case 2: document.write('这个月有28天'); break; case 4: case 6: case 9: case 11: document.write('这个月有30天'); break; } 当输出的值相同时,可以将多个case条件合并,结构如下: var xq = 7; switch (xq) { case 1: case 2: case 3: case 4: case 5: console.log('上班'); break; case 6: case 7: console.log('加班'); break; } 循环结构 工作原理:只要给定条件能得到满足,包含在循环语句里的代码就将重复地执行下去,一旦条件结果为false,循环即结束。 在javascript中,循环语句有三种,while、do…while、for循环 循环可以嵌套执行,最多三层嵌套,过多不利于理解。嵌套结构又称巢状结构 while循环 语法结构: // 当循环条件为true时,执行循环体, // 当循环条件为false时,结束循环。 初始值; while (循环条件) { //循环体 //改变循环条件 } 案例: // 计算1-100之间所有数的和 // 初始化变量 var i = 1; var sum = 0; // 判断条件 while (i <= 100) { // 循环体 sum += i; // 自增 i++; } console.log(sum); do…while循环 do…while循环和while循环非常像,二者经常可以相互替代,但是do…while的特点是不管条件成 不成立,都会执行一次。 语法结构: do { ​ // 循环体; } while (循环条件); 案例: //输出1到100值间的值 var i = 1,sum = 0; do { sum += i; //循环体 i++;//自增 } while (i <= 100);//循环条件 for循环 while和do…while一般用来解决无法确认次数的循环。 for循环 计数型循环 又称指定次数循环,for循环一般在循环次数确定的时候比较方便 语法结构: // for循环的表达式之间用的是;号分隔的 for (初始化表达式1; 判断表达式2; 自增表达式3) { // 循环体4 } 执行顺序:1243 ---- 243 -----243(直到循环条件变成false) 初始化表达式 判断表达式 自增表达式 循环体 案例: //输出1到10值间的数 for (var i = 1; i <= 10; i++) { document.write(i + ' '); } for循环的三个条件都可以提出来,通过if条件实现,注意需要有break跳出循环,否则会形成死循环。 for结构变形案例: var i = 1; for (;;) { if (i <= 10) { document.write(i + ' '); i++; } else { break; } } 练习: //打印正方形 var start = ''; for (var i = 0; i < 10; i++) { for (var j = 0; j < 10; j++) { start += '* '; } start += '\n'; } console.log(start); //打印直角三角形 var start = ''; for (var i = 0; i < 10; i++) { for (var j = i; j < 10; j++) { start += '* '; } start += '\n'; } console.log(start); //打印9*9乘法表 var str = ''; for (var i = 1; i <= 9; i++) { for (var j = i; j <=9; j++) { str += i + ' * ' + j + ' = ' + i * j + '\t'; } str += '\n'; } console.log(str); continue和break continue:跳出当前循环,继续下一次循环(跳到 j++ 的地方) break:跳出整个循环,即循环结束。开始执行循环后的内容。break2,退出2层循环。默认是break1,(只是 1 省略不写)即跳出1层循环。 练习: //输出 1 到 10 以内不包含 3 和 5 的数 for (var i = 1; i <= 10; i++) { ​ if (i == 3 || i == 5) { ​ //continue; ​ break; ​ } else { ​ document.write(i + ' '); ​ } ​} //求整数1~100的累加值,但要求碰到个位为3的数则停止累加 for (var i = 1,sum = 0; i <= 100; i++) { ​ if (i % 10 == 3) { ​ break; ​ } else { ​ sum += i; ​ } ​} ​document.write('1~100内碰到个位为3的数则停止累加值的和为:'+sum); //求整数1~100的累加值,但要求跳过所有个位为3的数 //sum 必须初始化为0,否则结果为未定义与数值相加,结果为NaN for (var i = 1,sum = 0; i <= 100; i++) { ​ if (i % 10 == 3) { ​ continue; ​ } else { ​ sum += i; ​ } ​} ​document.write('1~100内跳过个位为3的值的和为:'+ sum); 数组 数组的定义 之前学习的数据类型,只能存储一个值(比如:Number/String。我们想存储班级所有学生的成绩,此时 该如何存储? 此时就需要用到数组了。 定义 数组是值的有序集合,每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。 可以在数组中存放任意数据,并且数据的长度可以动态调整,根据需要它们会增长或缩减,创建数组时不需声明固定大小。 注意:数组元素的索引不一定要连续的,它们之间可以有空缺; 数组的数据类型为对象; 每个数组都有一个length属性。 语法结构: 通过构造函数创建数组: 有三种方式调用构造函数 a:调用时没有参数 该方法创建一个没有任何元素的空数组,等同于数组直接量[ ]。 var 数组名 = new Array(); b:调用时有一个数值参数,它指定长度。 var a = new Array(10);//创建指定长度为10的数组,每个数据是undefined 该方式创建指定长度的数组。当预先知道所需元素个数时,这种方式可以用来预分配一个数组空间。 注意:数组中没有存储值,甚至数组的索引属性‘0’,‘1’等还未定义。 c:显示指定多个数组元素,元素可为任意类型。 //多个值 这些值就代表数组中的元素 var arr3=new Array(10,20,1000,40,50,'test'); 通过数组字面量(直接量)创建数组 // 创建一个空数组 var arr1 = []; // 创建一个包含3个数值的数组,多个数组项以逗号隔开 var arr2 = [1, 3, 4]; // 创建一个包含3个不同类型的元素的数组 var arr3 = ['a', 1.1, true]; // 可以通过数组的length属性获取数组的长度 console.log(arr3.length); // 可以设置length属性改变数组中元素的个数 arr3.length = 0; 如果省略数组直接量中的某个值,省略的元素将被赋予undefined值。 var count = [1, ' ' , 3];//数组有三个值,中间那个元素的值为undefined。 数组直接量的语法允许有可选的结尾的逗号,故[, ,]只有两个元素而非三个元素。 var count = [ , , ];//数组有两个元素,值都为undefined。 注意与 PHP 的区分: php中有三种构建方法,除上述两种外还有一种 $var[] = ‘值’; 检测一个对象是数组 instanceOf Array.isArray() HTML5中提供的方法,有兼容性问题 var arr1 = [1,3,4]; console.log(arr1 instanceof Array);//true console.log(Array.isArray(arr1));//true toString()/valueOf() toString():把数组转换成字符串,并返回结果 语法: arrayObject.toString() 返回值 arrayObject 的字符串表示。返回值与没有参数的 join() 方法返回的字符串相同。 描述 数组中元素用逗号分隔。 var arr1 = [1,3,4]; console.log(arr1.toString());// '1,3,4' valueOf():返回数组对象本身 语法: arrayObject.valueOf() 描述 valueOf() 方法返回 Array 对象的原始值。 该原始值由 Array 对象派生的所有对象继承。 valueOf() 方法通常由 JavaScript 在后台自动调用,并不显式地出现在代码中。 var arr1 = [1,3,4]; console.log(arr1.valueOf());//(3) [1, 3, 4] 获取数组元素 (1)数组的取值 取值时,如果下标大于数组长度,则返回undefined。 // 格式:数组名[下标] 下标又称索引 // 功能:获取数组对应下标的那个值,如果下标不存在,则返回undefined。 var arr = ['red', 'green', 'blue']; arr[0]; // red arr[2]; // blue arr[3]; // 这个数组的最大下标为2,3>2,因此返回undefined (2)遍历数组 遍历:遍及所有,对数组的每一个元素都访问一次就叫遍历。 数组遍历的基本语法: 语法结构: for(var i = 0; i < arr.length; i++) { // 数组遍历的固定结构 } 数组中新增元素 数组的赋值: // 格式:数组名[下标/索引] = 值; // 如果下标有对应的值,会把原来的值覆盖,如果下标不存在,会给数组新增一个元素。 var arr = ["red", "green", "blue"]; arr[0] = "yellow"; // 把red替换成了yellow arr[3] = "pink";// 给数组新增加了一个pink的值 数组的赋值,必须有下标才能赋值,否则会报语法错误。如果是给没有下标的空数组赋值,可以用arr.length来表示下标。 //要求将数组中的0项去掉,将不为0的值存入一个新的数组,生成新的数组 var arr3 = [2,4,0,49,30,22,0,3]; var arr4 = []; for (var i = 0; i < arr3.length; i++) { //如果元素不为0 则存入到新数组中 if (arr3[i] != 0){ //数组赋值arr[] = 值;会报语法错误,因此赋值时不能省略下标的值。 //对于没有下标的数组,js中通常用arr.length来代表下标 arr4[arr4.length] = arr3[i]; } } console.log(arr4); console.log(typeof arr4);//object 删除数组元素 可以像删除对象属性一样使用delete运算符来删除数组元素: var arr = [1,2,3]; delete arr[1]; console.log(arr);//[1,3] console.log(arr.length);//3 delete不会改变数组长度 console.log(1 in arr);//false 1指的是索引 注意:对一个数组元素使用delete不会修改数组的length属性,也不会将元素从高索引处移下来填充已删除属性留下的空白。如果从数组中删除一个元素,它就变成稀疏数组。 冒泡算法 相邻两数比较,顶出最大的那个。 例如 :var arr = [50, 40, 30 ,20, 10]; [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Enl2dq8w-1574402375858)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570679410730.png)] var arr = [10, 30, 40, 60, 50, 20]; //i 为比较的轮数 最大值为 length-1 j 为比较的次数 最大值为 length-1-i for (var i=0; i < arr.length-1; i++) { for (var j=0; j < arr.length-1-i; j++) { if (arr[j] > arr[j+1]) { arr[j] = [arr[j+1], arr[j+1]=arr[j]][0]; } } } console.log(arr); 数组中常用函数 数组函数 解释说明 参数 返回值 栈操作 array.pop() 删除并返回数组的最后一个元素。改变数组长度 数组名 删除的元素 array.push() 向数组的末尾添加一个或多个元素,并返回新的长度。 要添加到数组的元素 返回新数组长度 array.shift() 把数组的第一个元素从其中删除,并返回第一个元素的值。 删除的元素 array.unshift() 向数组的开头添加一个或更多元素,并返回新的长度。 要添加到数组的元素 返回新数组长度 操作方法 array.concat() 连接两个或多个数组。不改变原数组 要连接的数组 返回被连接数组的副本 array.join() 数组中的所有元素按指定字符拼接成一个字符串。toString()与join同 可选,要指定的分隔符 返回新字符串 array.slice() 从已有的数组中返回选定的元素。不修改原数组 选取数组元素的起始位置,负数代表从后向前选,不包括end元素 返回选定的新数组 array.splice() 用于插入、删除或替换数组的元素。会修改数组 开始位置,删除长度[,要添加的元素] 返回新数组 颠倒数组元素 array.reverse() 颠倒数组元素的顺序。会改变原数组 返回新数组 排序方法 array.sort() 用于对数组的元素进行排序 [规定排序方式的函数] 返回新数组 位置方法 array.indexOf() 返回某个指定的字符串值在字符串中首次出现的位置。可用来判断数组中是否包含某个值,与in_array类似 规定需检索的字符串值[检索的位置] 返回下标数,没有返回 -1 array**.lastIndexOf()** 返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。 规定需检索的字符串值[检索的位置] 返回下标 迭代方法 some() 对数组中每一项运行给定函数, 回调函数 如果该函数对任一项返回true,则返回true。 every() 检测数组中的元素是否全部符合指定条件 回调函数 全部符合返回true 有一个不符合则返回false filter() 检测数组元素是否符合条件,并返回符合条件的元素的数组 回调函数 符合条件的元素的数组 forEach() 循环遍历数组 回调函数 map() 通过回调函数把每个元素的结果 保存到一个新数组中 进行返回 回调函数 返回执行回调函数的结果 清空数组 // 方式1 推荐 arr = []; // 方式2 arr.length = 0; // 方式3 arr.splice(0, arr.length); 练习 //求数组中的所有数的和 var arr = [10, 30, 40, 60, 50, 20]; for (var i=0,len=arr.length,sum=0; i<len; i++) { sum += arr[i]; } console.log(sum); //求数组中所有数的平均值 var len=arr.length;//为提高代码性能,避免每次循环都计算length,可以将length值赋给一个变量 for (var i=0,sum=0; i<len; i++) { sum += arr[i]; } var avg=sum/len; console.log(avg); //把数组中每个元素用|拼接到一起产生一个字符串并输出 var arr1 = [1,3,5,'aa']; //遍历出数组中的值并将值赋给一个空字符串,为避免字符串结果覆盖可以用 += 拼接结果 for (var i = 0,str = ''; i < arr1.length-1; i++) { str += arr1[i] + '|'; } //以上拼接结果会在字符串最后多出一个 | ,去掉最后的 | 可以在遍历时不遍历最后一个,而在打印结果时手动添加 console.log(str + arr1[arr1.length-1]); //要删除数组中元素为0的删除 var arr2 = [3,5,6,0,9,4,0,10,0]; //定义一个新数组 空的 var arr3 = []; for (var i = 0; i < arr2.length; i++) { //如果元素不为0 则存入到新数组中 if (arr2[i] != 0){ arr3[arr3.length] = arr2[i]; } } console.log(arr3); 函数 函数的定义 把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,就是函数,起个名字(函数 名),在后续开发中可以反复调用。 函数的作用就是封装一段代码,可以重复使用 。 语法结构: (1)声明函数 function 函数名(){ // 函数体 } (2)函数表达式 var fn = function() { // 函数体 } 特点: 函数声明的时候,函数体并不会执行,只有函数被调用的时候才会执行。 注意: 因为在js中回车换行可以表示语句的结束,所以书写时不要将函数的花括号换行到下一行,这点要与 php 相区分 规范 命名规范 遵循变量的命名规范 使用小驼峰命名法 命名一般采用 ‘‘动词+名字’’ 的形式,如 doSpeak 代码规范 1.命名规范 2.变量规范 var name = 'zs'; 3.注释规范 // 这里是注释 4.空格规范 5.换行规范 var arr = [1, 2, 3, 4]; if (a > b) { } for(var i = 0; i < 10; i++) { } function fn() { } 函数的调用 调用函数的语法结构: 函数名(); 特点: 函数体只有在调用的时候才会执行,调用需要 函数名() 进行调用。 可以调用多次(重复使用) 案例: // 声明函数 function sayHello() { console.log("你好啊!"); } // 调用函数 sayHello(); // 求1-100的和 function getSum() { var sum = 0; for (var i = 1; i <= 100; i++) { sum += i; } console.log(sum); } // 调用 getSum(); 函数的参数 语法结构: // 函数内部是一个封闭的环境,可以通过参数的方式,把外部的值传递给函数内部 // 带参数的函数声明 function 函数名(形参1, 形参2, 形参...){ // 函数体 } // 带参数的函数调用 函数名(实参1, 实参2, 实参3); 形参与实参: 形参:在声明函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值,我们可以设置形参。这些参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。 实参:如果函数在声明时,设置了形参,那么在函数调用的时候就要传入对应的参数,我们把传入的参数叫实际参数,也叫实参。 var x = 5, y = 6; fn(x,y); function fn(a, b) { console.log(a + b); } //x,y实参,有具体的值。函数执行的时候会把x,y复制一份给函数内部的a和b,函数内部的值是复制的新值,无法修改外部的x,y 函数的返回值 当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果 返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个 返回值 返回值语法: //声明一个带返回值的函数 function 函数名(形参1, 形参2, 形参...){ //函数体 return 返回值; } //可以通过变量来接收这个返回值 var 变量 = 函数名(实参1, 实参2, 实参3); 函数的调用结果就是返回值,因此我们可以直接对函数调用结果进行操作。 返回值详解: 如果函数没有显示的使用 return语句 ,那么函数有默认的返回值:undefined 如果函数使用 return语句,那么跟再return后面的值,就成了函数的返回值 如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined 函数使用return语句后,这个函数会在执行完 return 语句之后停止并立即退出,也就是说return后 面的所有其他代码都不会再执行。 推荐的做法是要么让函数始终都返回一个值,要么永远都不要返回值 arguments的使用 JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。也就是说 所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有的实参。 arguments 可以获取所有实参 arguments.length 获取实参的个数 arguments[i] 获取实参的值 //求任意数的和 function sum2(){ //可以获取所有实参 arguments.length 获取实参的个数 var sum = 0; for (var i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum; } console.log(sum2(2,35,6,8)); 匿名函数 匿名函数:没有名字的函数 匿名函数如何使用: 将匿名函数赋值给一个变量,这样就可以通过变量进行调用 //定义匿名函数 var f1 = function(){ return 'aaaaa'; }; console.log(f1()); 匿名函数自调用 //自调用函数 一次性,注意函数本身需加小括号才可以执行 js开发过程多用这种方式,命名函数在条件语句中有兼容问题 (function(){ console.log('aaaaaa'); })(); 关于自执行函数(匿名函数自调用)的作用:防止全局变量污染 //函数重名会覆盖上一函数,所以两次输出的结果相同 function a(){ console.log('你真好看'); } a(); function a(){ console.log('我真好看'); } a(); //匿名函数用var是声明变量,第二次不用var是给变量赋值,所以两次输出结果不一样 var b = function(){ console.log('你真好看'); }; b(); b = function(){ console.log('我真好看'); }; b(); 函数是一种数据类型 函数可以作为参数 可以把函数当做另一个函数的参数,在另一个函数中调用。此时作为参数的函数叫做回调函数(callback) //函数作为参数 function fn (fname) { fname();//a() } //命名函数作为参数 function a () { console.log('cccc'); } fn(a); //匿名函数作为参数 fn(function () { console.log('匿名函数'); }) var f = function () { console.log('将匿名函数赋值给变量f'); } fn(f);//先声明变量再调用,否则会报错。变量是先声明再赋值,而函数可以在任意位置调用,当fn(f)在声明f之前使用时,会出现函数名不能是函数的错误 函数可以作为返回值 可以把函数作为返回值从函数内部返回。调用时需要在后边加() //函数作为返回值 function freturn () { console.log('aaaa'); //return 将数据返回调用处,此时返回的是函数 return function () { console.log('bbbb'); } } //调用函数,因为返回值是一个函数,要想得到函数的值需要在后边再加括号 freturn()(); 回调函数的应用 //回调函数 callback /* 功能:计算两个数值 参数:第一个值,第二个值, fn 函数,第一个值与第二个值作为 fn 函数的参数 返回值:返回计算结果 */ function f1(a, b, fn) { return fn(a, b); } console.log(f1(1, 2, sum)); function sum (a, b) { return a + b; } 作用域 作用域:函数可以起作用的范围。 (1)全局变量和局部变量 局部作用域:函数体内 全局作用域:整个脚本,即函数内外都起作用 全局变量:在函数体外部由 var 定义的,在任何地方都可以访问的变量 局部变量:在函数体内用 var 定义的,只在函数内使用变量 隐式全局变量:不用 var 定义的变量,函数体内外都可以定义。在任何地方都可以访问 注意: 不使用var声明的变量是全局变量,不推荐使用。=变量退出作用域后会被销毁,全局变量关闭网页或浏览器才会销毁。 隐式全局变量与全局变量的区别: 隐式全局变量可以删除,而全局变量不可以删除,只有关闭浏览器或页面时才会销毁。 //全局变量: 在函数体外,由关键字var声明的变量 //全局作用域:整个脚本,即函数内外都起作用 var a = 'aaa'; function aa () { console.log(a);//函数体内调用变量 a } aa(); console.log(a); //函数体外调用变量 a //局部变量:在函数体内,由 var 声明的变量 //局部作用域:只在函数体内起作用 function bb () { var b = 'bbbb'; console.log(b);//函数体内调用 输出 bbbb } bb(); //console.log(b);//报错 在函数体外调用会,指出变量不存在 //隐式全局变量 声明变量,但是没有 var 。作用域函数内外都可 //隐式全局变量与全局变量的区别,隐式全局变量可以删除,而全局变量不能删除,只有在关闭网页或浏览器时才会销毁 c = 'cccc'; console.log(c); //函数体外调用 返回 cccc function cc () { console.log(c); //函数体内调用 返回 cccc } cc(); delete c;//删除隐式全局变量 //console.log(c);//报错,说变量不存在。说明删除成功 delete a; console.log(a+'删除全局变量失败');//aaa删除全局变量失败 正常输出a的值,说明没有删除变量 (2)块级作用域 任意一个花括号内的语句集都属于一个块,其中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。==在ES5之前没有块级作用域的概念,只有函数作用域。==ES6中才有块级作用域 (3)词法作用域 变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能 确定,因此词法作用域也叫做静态作用域 在js中词法作用域规则: 函数允许访问函数外的数据. 整个代码结构中只有函数可以限定作用域. 作用域规则首先使用提升规则分析 如果当前作用规则中有名字了, 就不考虑外面的名字。即当局部变量与全局变量同名时,采用局部变量 var num = 123; //全局变量 function foo() { console.log( num ); } foo(); // 123 if ( false ) { //条件是假区间,永远走不进区间里,不会声明变量 num var num = 123; } console.log( num ); // undefiend (4)作用域链 只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函 数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用 域。 将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。 function f1() { var num = 123; //局部变量,就近原则 function f2() { console.log( num ); } f2(); //返回 num = 123 } var num = 456; //全局变量 f1();//函数值返回调用处,所以不会走到重新声明 num 的语句 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x8lXAGpL-1574402375863)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570718544910.png)] 预解析**** JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码 的时候,分为两个过程:预解析过程和代码执行过程 预解析过程(提升规则): 把变量的声明提升到当前作用域的前面,只会提升声明,不会提升赋值。 把函数的声明提升到当前作用域的前面,只会提升声明,不会提升调用。 先提升var,再提升function 执行过程 b(); var a = 1; function b () { console.log(a); } //预解析过程 /* var a; function b () { console.log(a); } b(); a = 1; */ f1(); console.log(c); console.log(b); console.log(a); function f1() { var a = b = c = 9; console.log(a); console.log(b); console.log(c); } //预解析过程 以下代码为上述代码解析后的样式,执行将按这个顺序 /*function f1() { var a; a = 9;//局部变量 b = 9;//隐式全局变量 c = 9;//隐式全局变量 console.log(a); //9 console.log(b); //9 console.log(c); //9 } f1(); console.log(c); //9 console.log(b); //9 console.log(a); //报错 */ var a = 25; function abc (){ alert(a);//undefined var a = 10; } abc(); //预解析过程 /* var a; function abc (){ var a; alert(a);//undefined a = 10; } a = 25; abc(); */ // 如果变量和函数同名的话,函数优先 console.log(a); function a() { console.log('aaaaa'); } var a = 1; console.log(a); //预解析过程 /* var a; function a() { console.log('aaaaa'); } console.log(a); //返回值为函数本身 a = 1; console.log(a); //1 */ 练习 //返回两个数中的最大值 function max(a,b){ if(a > b){ document.write("最大值为" + a); }else{ document.write("最大值为" + b); } } max(10, 20); 对象 什么是对象 现实生活中:万物皆对象,对象是一个具体的事物,一个具体的事物就会有行为和特征。 举例: 一部车,一个手机 车是一类事物,门口停的那辆车才是对象 特征:红色、四个轮子 行为:驾驶、刹车 **JavaScript中的对象是无序属性的集合。**可以把js对象想象成键值对,其中值可以是数据和函数。 对象的行为和特征 特征:属性 行为:方法 内建对象:Array, Math, Date等 宿主对象:由浏览器提供的预定义对象。如image、form、Element等。 创建对象 语法结构: (1)对象字面量 语法结构: var 对象名 = {} 案例: var obj = {}; obj.name = '章'; obj.age = 18; obj.sex = '女'; obj.say = function () { console.log('说话'); } console.log(obj); //优化写法 var o = { name: 'zs, age: 18, sex: true, sayHi: function () { console.log(this.name); } }; (2)构造函数方式创建 a:系统内置构造函数 new Object() var person = new Object(); person.name = 'lisi'; person.age = 35; person.job = 'actor'; person.sayHi = function(){ console.log('Hello,everyBody'); } b:工厂函数创建对象 function createPerson(name, age, job) { var person = new Object(); person.name = name; person.age = age; person.job = job; person.sayHi = function(){ console.log('Hello,everyBody'); } return person; } var p1 = createPerson('张三', 22, 'actor'); (3)自定义构造函数 构造函数 构造函数是一种特殊的函数,主要用来在创建对象时初始化对象,即为对象的成员属性赋初值。 注意事项: (1)构造函数用于创建一类对象,首字母要大写; (2)构造函数要和new一起用才有意义。 new在执行时会做四件事: (1)在内存中创建一个空的对象; (2)让this指向这个新对象; (3)执行构造函数,目的是给这个对象添加属性和方法; (4)返回这个新对象。 function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayHi = function(){ console.log('Hello,everyBody'); } } var p1 = new Person('张三', 22, 'actor'); this详解 JavaScript中的this指向问题,有时候会让人难以捉摸,随着学习的深入,我们可以逐渐了解。现在我们需要掌握函数内部的this几个特点 函数在定义的时候this是不确定的,只有在调用的时候才可以确定 一般函数直接执行,内部this指向全局window 函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象 构造函数中的this其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到了这个 隐式对象身上,后续通过new关键字来调用,从而实现实例化 对象的属性与方法 属性:对象的特征 变量 方法:对象的行为 函数 可以使用下面两种方式访问对象的属性和方法 1.对象名.属性名 对象名.方法名() 2.对象名[“属性名”] 对象名 [‘方法名’] () 两者的区别: 对于已经存在的属性和方法,用.和用[]得到的结果一致、 对于不存在(未定义)的属性和方法,用.会创建这个新的属性或方法,而用[]的方式访问不会创建新的属性或方法 var obj = new Object(); //console.log(typeof obj); //给对象添加属性 对象.属性名 = 值 obj.name = 'hanxu'; obj.age = 10; obj.sex = 'll'; obj.hair = false; obj.eye = 'three';//给对象添加方法 函数 对象.函数名 = 函数 obj.sleep = function(){ console.log('天天睡觉,回家放羊吧!!!'); } obj.eat = function () { console.log('做梦吃烤全羊'); } //获取对象属性 console.log(obj.name); console.log(obj.age); obj.eat(); //两种访问 方式的区别 var obj = { name : "小明", age : 18, say : function(){ console.log("我是"+this.name+"我"+this.age+"岁"); } }; //对比 . 与 [] 的区别 for(var x in obj){ console.log(x); //输出obj中的属性名,方法名 console.log(obj.x);//想要用.的方法输出对应的属性和方法 结果是undefined,原因在于JS语言中.方法可以用来声明,声明对象属性的方式就是属性名.属性值 } for (var key in obj) { console.log(key);//输出obj中的属性名,方法名 console.log(obj[key]);//输出对应的属性值和方法,方法未调用所以输出的是方法的代码 } 遍历对象的属性 通过for…in语法可以遍历一个对象 For…In 声明用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。 for … in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。 语法结构: for (变量 in 对象) { 在此执行代码 } 变量”用来指定变量,指定的变量可以是数组元素,也可以是对象的属性。 var obj = {}; for (var i = 0; i < 10; i++) { obj[i] = i * 2; } for(var key in obj) { console.log(key + "==" + obj[key]); } 删除对象的属性 语法结构: delete 对象.属性名 function fun() { this.name = 'mm'; } var obj = new fun(); console.log(obj.name); // mm delete obj.name; console.log(obj.name); // undefined 内置函数 Math Math对象不是构造函数,它具有数学常数和函数的属性和方法,都是以静态成员的方式提供 。 使用的时候不需要new (1)Math.PI – 算数常量 π 语法结构: Math.Pi console.log(Math.PI);//3.141592653589793 表示的是常量 π 或 pi,即圆的周长和它的直径之比,这个值近似为3.14159265358979。 因为是常量,所以后边没有小括号 (2)Math.random – 生成随机数 语法结构: Math.random() console.log(Math.random()); 返回值 返回一个0.0 和 1.0之间的一个伪随机数。 获取n-m之间的随机数 function rand(n, m) { return Math.round(Math.random()*(n-m)+m); } (3)Math.ceil – 向下取整 语法结构: Math.ceil(x) //向下取整/进一法取整 解释说明 Math.ceil() 执行的是向上取整计算,它返回的是大于等于函数参数,并且与之最接近的整数。需要注意的是, Math.ceil()不会将负数舍人为更小的负数,而是向0舍入。 参数 x 任意的数值或表达式。 返回值 大于等于x,并且与它最接近的整数。 示例: `a = Math.ceil(1.99); // 结果是 2.0 b = Math.ceil(1.01); // 结果是 2.0 c = Math.ceil(1.0); // 结果是 1.0 d = Math.ceil(-1.99); // 结果是 -1.0 ` (4)Math.floor – 向上取整 语法结构: `Math.floor(*x*)` 描述 Math.floor()执行的是向上取整计算,它返回的是小于等于函数参数,并且与之最接近的整数。 Math.floor()将一个浮点值下舍人为最接近的整数。Math.floor()执行的操作不同于Math.round(),它总是进行下舍人,而不是上舍入或下舍人到最接近的整数。还要注意,Math.floor()将负数舍入为更小的负数,而不是向0进行舍入。 参数 x 任意的数值或表达式。 返回值 小于等于x,并且与它最接近的整数。 示例: console.log( Math.floor(1.99)); // 结果为1 console.log( Math.floor(1.01)); // 结果为1 console.log( Math.floor(1.0)); // 结果为1 console.log( Math.floor(-1.01)); // 结果为-2 (5)Math.round() – 四舍五入 语法结构: `Math.round(*x*)` 描述 Math.round( )将把它的参数上舍入或下舍入到与它最接近的整数。注意对于0.5,它将向上舍入。例如,2.5将被舍入为3,-2.5将被舍入为-2。 console.log(Math.round(5.6));//6 console.log(Math.round(5.1));//5 console.log(Math.round(5.5));//6 console.log(Math.round(-5.1));//-5 console.log(Math.round(-5.6));//-6 console.log(Math.round(-5.5));//-5 (6)Math.abs( ) – 求绝对值 console.log(Math.abs(5.6));//5.6 console.log(Math.abs(-5.6));//5.6 console.log(Math.abs(6));//6 (7)Math.max – 最大值 Math.min – 最小值 语法结构: `Math.max(*args...*)` 参数 args 0个或多个值。在ECMAScriptv3之前,该方法只有两个参数。 返回值 Math.max() 返回参数中最大的值。如果没有参数,返回-Infinity。如果有一个参数为NaN,或是不能转换成数字的非数字值,则返回 NaN。 Math.min() 返回参数中最小的值。如果没有参数,返回Infinity。如果有一个参数为NaN,或是不能转换成数字的非数字值,则返 NaN。 示例: console.log(Math.min(1,4,7,9));// 1 console.log(Math.max(1,4,7,9));// 9 console.log(Math.max(1,4,7,9,'av'));// NaN console.log(Math.min(1,4,7,9,'av'));//NaN console.log(Math.min());//Infinity console.log(Math.max());//-Infinity (8)Math.sin() – 正弦 Math.cos() – 余弦 语法结构: `Math.cos(*x*)` 参数 x 一个角的弧度值。要把角度转换成弧度,只需把角度值乘以(2π/360)。 返回值 Math.cos() 指定的值x的余弦值。返回的是-1.0 和 1.0. Math.sin() 指定的值x的余弦值。返回的是-1.0 和 1.0. (9)Math.pow – 求指数次幂 Math.sqrt() – 求平方根 语法结构: `Math.pow(*x*, *y*) ` 描述 Math.pow() 如果结果是虚数或负数,则该方法将返回 NaN。如果由于指数过大而引起浮点溢出,则该方法将返回 Infinity 参数 Math.pow() x 必需。底数,必须是数字 y 必需。幂数,必须是数字 Math.sprt() x 必须。必须是大于等于 0 的数 返回值 Math.pow() 返回x 的 y 次幂。 Math.sprt() 返回参数 x 的平方根。如果 x 小于 0,则返回 NaN。 //Math.pow() document.write(Math.pow(0,0) + "<br />");//1 document.write(Math.pow(0,1) + "<br />");//0 document.write(Math.pow(1,1) + "<br />");//1 document.write(Math.pow(1,10) + "<br />");//1 document.write(Math.pow(2,3) + "<br />");//8 document.write(Math.pow(-2,3) + "<br />");//-8 document.write(Math.pow(2,4) + "<br />");//16 document.write(Math.pow(-2,4) + "<br />");//-16 //Math.sprt() document.write(Math.sqrt(0) + "<br />")//0 document.write(Math.sqrt(1) + "<br />")//1 document.write(Math.sqrt(9) + "<br />")//3 document.write(Math.sqrt(0.64) + "<br />")//0.8 document.write(Math.sqrt(-9))//NaN (8)toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。 (9)案例 // 10 - 20 之间的随机数 var rand = Math.floor(Math.random()*10+10); console.log(rand); //随机生成颜色RGB function getRandColor () { var colorValue = [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f']; var s = '#'; for (var i = 0; i < 6; i++) { s += colorValue[Math.floor(Math.random()*16)]; } return s; } document.write(getRandColor ()); Date 对象 创建 Date 实例用来处理日期和时间。Date 对象基于1970年1月1日(世界标准时间)起的毫秒数。 (1)创建 Date 对象的语法: var myDate = new Date(); //获取当前日期的时间戳 var now = new Date(); //console.log(now); 默认是返回时间的英文格式 // valueOf用于获取对象的时间戳 console.log(now.valueOf()); // HTML5中提供的方法,有兼容性问题 var now = Date.now(); // 返回毫秒数 // 不支持HTML5的浏览器,可以用下面这种方式 var now = + new Date(); // 调用 Date对象的valueOf() (2)Date 构造函数的参数 毫秒数 1498099000356 new Date(1498099000356) 日期格式字符串 ‘2015-5-1’ new Date(‘2015-5-1’) 年、月、日…… new Date(2015, 4, 1) // 月份从0开始 //获取指定时间 var now = new Date(2015,0,6);//不加引号月份从0开始 var now1 = new Date('2015,1,6');//加引号月份从1开始 var now2 = new Date('2015-1-6');//同上 console.log(now); console.log(now1); console.log(now2); (3)格式化日期的方法 toString() // 转换成字符串 valueOf() // 获取毫秒值 // 下面格式化日期的方法,在不同浏览器可能表现不一致,一般不用 toDateString() //英文模式 toTimeString() //中国时间,时分秒 toLocaleDateString() //年/月/日 toLocaleTimeString() //下午 时分秒 //获取 年-月-日 时:分:秒(需要判断去掉 上/下午) dd.toLocaleDateString() + dd.toLocaleTimeString() 示例: var now = new Date('2015-01-15'); console.log(now.toDateString()); //Thu Jan 15 2015 console.log(now.toTimeString()); //08:00:00 GMT+0800 (中国标准时间) console.log(now.toLocaleDateString());//2015/1/15 console.log(now.toLocaleTimeString());//上午8:00:00 (4)Date 对象的方法 getTime() // 返回毫秒数和valueOf()结果一样,valueOf()内部调用的getTime() getMilliseconds() getSeconds() // 返回秒 0-59 getMinutes() // 返回分 0-59 getHours() // 返回时 0-23 getDay() // 返回星期几 0代表周日 6代表周6 getDate() // 返回当前月的第几天 getMonth() // 返回月份,从0开始 getFullYear() //返回4位的年份 如 2016 toDateString() //英文模式 toTimeString() //中国时间,时分秒 toLocaleDateString() //年/月/日 toLocaleTimeString() //下午 时分秒 示例: var now = new Date('2019-10-15 06:00:05'); console.log(now.getTime());//获取时间戳 console.log(now.getSeconds());//获取指定时间的秒 console.log(now.getMinutes());//获取指定时间的分 console.log(now.getHours());//获取指定时间的分 console.log(now.getDay());//获取指定日期是星期几 console.log(now.getDate());//获取指定日期是当月的第几天 console.log(now.getMonth());//获取指定日期的月份,从0开始 console.log(now.getFullYear());//获取指定日期的四位数年份 // 去掉获取时间格式的 上下午 var time = new Date().toLocaleTimeString(); function conversionTime (time) { var daytime = time.substring(0,2);//截取汉字上下午 var currentTime = time.substring(2,time.length);//截取除上下午之外的时间 var timeList = currentTime.split(':');//转化为数组 console.log(timeList); if (daytime === '下午' && timeList[0] <= 12) { //对下午时间进行操作 timeList[0] = *Number*(timeList[0]) + 12;//第0个元素为当前小时数 + 12 currentTime = timeList.toString().replace(/,/g,';');//toString 将数组拼接成字符串 } return currentTime; } console.log(conversionTime (time)); 练习: 获取某月有多少天? 思路: new Date() 第三个参数默认为 1,就是每个月的 1 号,把它设置为 0 时,new Date() 会返回上一个月的最后一天,然后通过 getDate() 方法得到天数,所以month 的值本应该是 +1。但是需要注意的是,Date 函数中的月份是从 0 开始的,所以这里直接用 month的值即可。 //获取某月有多少天 function getMonthDay (year, month) { var days = new Date(year,month,0).getDate(); return days; } console.log(getMonthDay(2019,5)); Array() 其他数组函数见 第9章 数组 中的数组常用函数 every() – 检测数组所有元素是否都符合指定条件 语法结构: bool array.every(function(currentValue[,index,arr]), thisValue) 描述/返回值 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测 如果所有元素都满足条件,则返回true 参数 function 必须是函数。数组中的每个元素都会执行这个函数. ​ 函数的参数:currentValue 必选 当前元素的值。 ​ index 可选 当前元素的索引值。 ​ arr 可选 当前元素所属的数组对象 thisValue 可选。对象作为该执行回调时使用,传递给函数,用作 “this” 的值。 如果省略了 thisValue ,“this” 的值为 “undefined” 注意: every() 不会对空数组进行检测 every() 不会改变原始数组 示例: var eArr = [1,8]; function check (eArr) { return eArr >= 7; } document.write(eArr.every(check)); 检测一个对象是否是数组 instanceof Array.isArray() HTML5中提供的方法,有兼容性问题 函数的参数,如果要求是一个数组的话,可以用这种方式来进行判断 toString()/valueOf() toString() 把数组转换成字符串,逗号分隔每一项 valueOf() 返回数组对象本身 数组常用函数 见数组章节 后续补充 some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。 用法,参数,返回值同every() every()与some()方法都是JS中数组的迭代方法。 every()是对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true。 filter() – 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 语法结构: bool array.every(function(currentValue[,index,arr]), thisValue) 参数 function 必须是函数。数组中的每个元素都会执行这个函数. ​ 函数的参数:currentValue 必选 当前元素的值。 ​ index 可选 当前元素的索引值。 ​ arr 可选 当前元素所属的数组对象 thisValue 可选。对象作为该执行回调时使用,传递给函数,用作 “this” 的值。 如果省略了 thisValue ,“this” 的值为 “undefined” 注意: every() 不会对空数组进行检测 every() 不会改变原始数组 返回值 返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组。 示例: var eArr = [1,8]; function check (eArr) { return eArr >= 7; } document.write(eArr.every(check)); forEach() – 遍历数组用于调用数组的每个元素,并将元素传递给回调函数。 语法结构: undeifined array.forEach(function(currentValue, index, arr), thisValue) 参数 参数 描述 function(currentValue, index, arr) 必需。 数组中每个元素需要调用的函数。 函数参数: 参数 描述 currentValue 必需。当前元素 index 可选。当前元素的索引值。 arr 可选。当前元素所属的数组对象。 thisValue 可选。传递给函数的值一般用 “this” 值。 如果这个参数为空, “undefined” 会传递给 “this” 值 返回值 undeifined 注意: forEach() 对于空数组是不会执行回调函数的。 示例: var numbers = [65, 44, 12, 4]; numbers.forEach(function(ele,index){ console.log(index+'--'+ele); }); map() – 让数组中的元素依次执行回调函数,并将结果返回 String() 字符串可以看成是一组字符组成的数组 特性:值不可变 可访问 获取 不可修改 (1)String 对象的不可变性 当重新给str赋值的时候,常量’abc’不会被修改,依然在内存中 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变性 由于字符串的不可变,在大量拼接字符串的时候会有效率问题 (2)创建字符串对象 var str = new String('Hello World'); // 获取字符串中字符的个数 console.log(str.length); (3)字符串对象的常用方法 字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串 // 1 字符方法 charAt() //获取指定位置处字符 charCodeAt() //获取指定位置处字符的ASCII码 str[0] //HTML5,IE8+支持 和charAt()等效 // 2 字符串操作方法 concat() //拼接字符串,等效于+,+更常用 slice(start,end) //从start位置开始,截取到end位置,end取不到,负数代表从后开始取 substring(start,end) //从start位置开始,截取到end位置,end取不到 //slice 与 substring 的不同之处是 slice 参数可以是负数,而substring参数不可以是负数 substr(start,length) //从start位置开始,截取length个字符 // 3 位置方法 indexOf() //返回指定内容在元字符串中的位置 lastIndexOf() //从后往前找,只找第一个匹配的 // 4 去除空白 trim() //只能去除字符串前后的空白 // 5 大小写转换方法 to(Locale)UpperCase() //转换大写 to(Locale)LowerCase() //转换小写 // 6 其它 search(reg/str) //用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。查不到返回-1,查到返回0或大于0的数 replace(要替换的字符,替换成的字符) //可用一个新文档取代当前文档。 split(分隔符[,截取的长度]) //把一个字符串分割成字符串数组。 fromCharCode() // String.fromCharCode(101, 102, 103); //把ASCII码转换成字符串 示例: //字符串相关方法 字符串方法不改变原字符串 //.charAt(index) 返回字符串指定字符 var str = 'abfWFRGfag4dd'; console.log(str.charAt(3));//d //.charCodeAt(index) 对应字符 ASCII 表 或 UTF系列 中数据 console.log(str.charCodeAt(3));//100 //concat 连接多个字符串 var str1 = '123'; var str2 = '456'; console.log(str.concat(str2,str1));//abfds3fag4dd456123 console.log(str.concat(str1,str2));//abfds3fag4dd123456 //indexOf(str, fromIndex) 寻找指定字符的位置 从前向后去搜索 如果找到则返回对应的索引位置 如果没有找到返回-1 // 如果没给第二个参数 默认从0开始 如果指定第二个参数 从指定开始向后找 // 包含当前fromIndex console.log(str.indexOf('f'));//2 console.log(str.indexOf('f',3));//5 //lastIndexOf() 同上,从后向前找 console.log(str.lastIndexOf('f'));//5 console.log(str.lastIndexOf('f',4));//5 //replace(要替换的字符串,替换成什么) 只能改变第一个符合条件的字符,如果向改变所有字符需要用正则 console.log(str.replace('a','我'));//我bfdsfag4dd console.log(str.replace(/a/g,'我'));//我bfdsf我g4dd //slice(start[,end]) 从start到end(不包含end)值间取出 取出一部分 新的字符串 并返回这部分字符串 取注意 取到end之前不包含end console.log(str.slice(2,4));//fd //split(分隔符[,分隔后取几个]) 返回数组 var ss = 'aa | bb | cc | dd'; console.log(ss.split('|')); console.log(ss.split('|',1)); //substr(startindex [,length]) //substring(startIndex [,endIndex]) 注意:不包含endIndex console.log(str.substr(2,3));//fds console.log(str.substring(2,3));//f //toLowerCase() 常用 //toLocaleLowerCase() 包含语言比较多 //toUpperCase() //toLocaleUpperCase(); console.log(str.toLowerCase()); console.log(str.toLocaleLowerCase()); console.log(str.toUpperCase()); console.log(str.toLocaleUpperCase()); //.trim()去除字符串两端留白 var st = ' --dsf-- '; console.log(st); console.log(st.trim()); a: slice() – 提取字符串的某个部分,并以新的字符串返回被提取的部分。 stringObject.slice(start,end) 参数 描述 start 要抽取的片断的起始下标。如果是负数,则该参数规定的是从字符串的尾部开始算起的位置。也就是说,-1 指字符串的最后一个字符,-2 指倒数第二个字符,以此类推。 end 紧接着要抽取的片段的结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。 返回值 一个新的字符串。包括字符串 stringObject 从 start 开始(包括 start)到 end 结束(不包括 end)为止的所有字符。 说明 String 对象的方法 slice()、substring() 和 substr() (不建议使用)都可返回字符串的指定部分。slice() 比 substring() 要灵活一些,因为它允许使用负数作为参数。slice() 与 substr() 有所不同,因为它用两个字符的位置来指定子串,而 substr() 则用字符位置和长度来指定子串。 还要注意的是,String.slice() 与 Array.slice() 相似。 var str="Hello happy world!" document.write(str.slice(6))//happy world! b:split() – 把字符串分隔成数组 stringObject.split(separator,howmany) 参数 描述 separator 必需。字符串或正则表达式,从该参数指定的地方分割 stringObject。 howmany 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。 返回值 一个字符串数组。该数组是通过在 separator 指定的边界处将字符串 stringObject 分割成子串创建的。返回的数组中的字串不包括 separator 自身。 但是,如果 separator 是包含子表达式的正则表达式,那么返回的数组中包括与这些子表达式匹配的字串(但不包括与整个正则表达式匹配的文本)。 注释: 如果把空字符串 ("") 用作 separator,那么 stringObject 中的每个字符之间都会被分割。 String.split() 执行的操作与 Array.join 执行的操作是相反的。 var str="How are you doing today?" document.write(str.split(" ") + "<br />")//How,are,you,doing,today? document.write(str.split("") + "<br />")//H,o,w, ,a,r,e, ,y,o,u, ,d,o,i,n,g, ,t,o,d,a,y,? document.write(str.split(" ",3))//How,are,you 练习 //截取字符串"我爱中华人民共和国",中的"中华" var s = "我爱中华人民共和国"; s = s.substr(2,2); console.log(s); //"aobocoddddgho"查找字符串中所有o出现的位置 var s = 'abcoefoxyozzopp'; var array = []; do { var index = s.indexOf('o', index + 1); if (index != -1) { array.push(index); } } while (index > -1); console.log(array); //把字符串中所有的o替换成! var s = 'abcoefoxyozzopp'; do { s = s.replace('o', ''); } while (s.indexOf('o') > -1); console.log(s); console.log(s.replace(/o/ig, '')); 基本包装类型 为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String/Number/Boolean 即字符串、数字、布尔在使用对象的 ( . ) 方法访问其方法或属性时,会自动转成类对象的模式,这种类型被称为基本包装类型。 特点是:基本包装类型是暂时的,并没有改变的数据类型,使用结束后即销毁。 Number和Boolean基本包装类型基本不用,使用的话可能会引起歧义 // 下面代码的问题? // s1是基本类型,基本类型是没有方法的 var s1 = 'zhangsan'; var s2 = s1.substring(5); // 当调用s1.substring(5)的时候,先把s1包装成String类型的临时对象,再调用substring方法, 后销毁临时对象, 相当于: var s1 = new String('zhangsan'); var s2 = s1.substring(5); s1 = null; // 创建基本包装类型的对象 var num = 18; //数值,基本类型 var num = Number('18'); //类型转换 var num = new Number(18); //基本包装类型,对象 // Number和Boolean基本包装类型基本不用,使用的话可能会引起歧义。例如: var b1 = new Boolean(false); var b2 = b1 && true; console.log(b2); // 结果是 true,而交换两个操作数之后呢 var b3 = true && b1; console.log(b3); //Boolean{false},返回的是一个值为 false 的对象 JavaScript错误 语句 描述 try 测试代码块错误,包括语法错误、拼写错误、服务器或用户错误等等。 catch 处理错误语句 throw 抛出错误 finallly 用在try catch之后,无论是否有触发异常,都会执行 语法: try { ... //异常的抛出 } catch(e) { ... //异常的捕获与处理 } finally { ... //结束处理 } <input type="button" value="查看消息" onclick="isError()"> <script> ​ txt = ""; ​ *function* isError(){ ​ try { ​ addlert("hello world"); ​ }catch(err){ ​ txt = "本页有一个错误"; ​ txt += "错误描述" + err.message + "\n"; ​ *var* ara = *Object*.getOwnPropertyNames(err); ​ *console*.log(typeof err); ​ *console*.log(ara); ​ alert(txt); ​ } ​ } ​ </script> 严格模式 “use strict” 指令在 JavaScript 1.8.5 (ECMAScript5) 中新增。 它不是一条语句,但是是一个字面量表达式,在 JavaScript 旧版本中会被忽略。 “use strict” 的目的是指定代码在严格条件下执行。 严格模式下你不能使用未声明的变量。 支持严格格式的浏览器: Internet Explorer 10 +、 Firefox 4+ Chrome 13+、 Safari 5.1+、 Opera 12+。 为什么使用严格模式: 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为; 消除代码运行的一些不安全之处,保证代码运行的安全; 提高编译器效率,增加运行速度; 为未来新版本的Javascript做好铺垫。 严格模式的限制 不允许使用未声明的变量,对象也是变量 不允许删除变量或对象,不允许删除函数 不允许变量重名 不允许使用八进制 不允许使用转义字符 不允许对只读属性赋值 不允许对使用getter方法获取的属性赋值 不允许删除一个不允许删除的属性 变量名不能使用eval、arguments关键字 禁止this指向全局对象 表单验证 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pMlYmrPn-1574402375865)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20191118220000688.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f8TIti3u-1574402375866)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20191118220039266.png)] 数据验证 典型的数据验证有: 必需字段是否输入 用户是否输入了合法的路径 是否在数字字段输入文本 HTML约束 约束验证是表单被提交时浏览器用来实现验证的一种算法。 HTML 约束验证基于: HTML 输入属性 CSS 伪类选择器 DOM 属性和方法 约束验证 HTML 输入属性 属性 描述 disabled 规定输入的元素不可用 max 规定输入元素的最大值 min 规定输入元素的最小值 pattern 规定输入元素值的模式 required 规定输入元素字段是必需的 type 规定输入元素的类型 JSON JSON 是用于存储和传输数据的格式。 JSON 通常用于服务端向网页传递数据 。 什么是json websocktet 1、背景 很多网站为了实现推送技术,所用的技术都是Ajax轮询。轮询是在特定的的时间间隔由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。HTML5新增的一些新协议WebSocket,可以提供在单个TCP连接上提供全双工,双向通信,能够节省服务器资源和带宽,并且能够实时进行通信。 2、WebSocket 传统的http也是一种协议,WebSocket是一种协议,使用http服务器无法实现WebSocket, 2.1.浏览器支持情况 基本主流浏览器都支持 2.2.优点 相对于http有如下好处: 1.客户端与服务器只建立一个TCP连接,可以使用更少的连接。 2.WebSocket服务器端可以主动推送数据到客户端,更灵活高效。 3.更轻量级的协议头,减少数据传送量。 对比轮训机制 3、WebSocket用法 我们了解WebSocket是什么,有哪些优点后,怎么使用呢? 3.1.WebSocket创建 WebSocket使用了自定义协议,url模式与http略有不同,未加密的连接是ws://,加密的连接是wss://,WebSocket实例使用new WebSocket()方法来创建, var Socket = new WebSocket(url, [protocol] ); 第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。 3.2.WebSocket属性 当创建ws对象后,readyState为ws实例状态,共4种状态 0 表示连接尚未建立。 1 表示连接已建立,可以进行通信。 2 表示连接正在进行关闭。 3 表示连接已经关闭或者连接不能打开。 **Tips:**在发送报文之前要判断状态,断开也应该有重连机制。 3.3.WebSocket事件 在创建ws实例对象后,会拥有以下几个事件,根据不同状态可在事件回调写方法。 ws.onopen 连接建立时触发 ws.onmessage 客户端接收服务端数据时触发 ws.onerror 通信发生错误时触发 ws.onclose 连接关闭时触发 ws.onmessage = (res) => { console.log(res.data); }; ws.onopen = () => { console.log('OPEN...'); }; ws.onclose=()=>{ console.log('CLOSE...'); } 3.4.WebSocket方法 ws.send() 使用连接发送数据(只能发送纯文本数据) ws.close() 关闭连接 4、Demo演示 了解WebSocket的一些API之后,趁热打铁,做一个小案例跑一下。 4.1.Node服务器端 WebSocket协议与Node一起用非常好,原因有以下两点: 1.WebSocket客户端基于事件编程与Node中自定义事件差不多。 2.WebSocket实现客户端与服务器端长连接,Node基本事件驱动的方式十分适合高并发连接 创建一个webSocket.js如下: const WebSocketServer = require('ws').Server; const wss = new WebSocketServer({ port: 8080 }); wss.on('connection', function (ws) { console.log('client connected'); ws.on('message', function (message) { ws.send('我收到了' + message); }); }); 打开windows命令窗口运行 4.2.HTML客户端 新建一个index.html页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webSocket小Demo</title> </head> <body> <div class="container"> <div> <input type="text" id="msg"> <button onclick="sendMsg()">发送报文</button> </div> </div> <script> const ws = new WebSocket('ws://localhost:8080'); ws.onmessage = (res) => { console.log(res); }; ws.onopen = () => { console.log('OPEN...'); }; ws.onclose = () => { console.log('CLOSE...'); } function sendMsg() { let msg = document.getElementById('msg').value; ws.send(msg); } </script> </body> 打开浏览器依次输入字符1,2,3,每次输入完点击发送报体,可见在ws.onmessage事件中res.data中返回来我们发的报文 5、问题与总结 以上只是简单的介绍了下WebSocket的API与简单用法,在处理高并发,长连接这些需求上,例如聊天室,可能WebSocket的http请求更加合适高效。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册