本文将介绍JavaScript专项练习:函数篇的详细情况,特别是关于一的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于1+x证书Web前端开发HTM
本文将介绍JavaScript 专项练习:函数篇的详细情况,特别是关于一的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于1+x 证书 Web 前端开发 HTML5 专项练习、2019 天梯赛练习题(L2 专项练习)、GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function、Javascript 与 CSS,JavaScript 的动态加载技术的知识。
本文目录一览:- JavaScript 专项练习:函数篇(一)(javascript函数题)
- 1+x 证书 Web 前端开发 HTML5 专项练习
- 2019 天梯赛练习题(L2 专项练习)
- GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function
- Javascript 与 CSS,JavaScript 的动态加载技术
JavaScript 专项练习:函数篇(一)(javascript函数题)
引言
在学习 JavaScript 的过程中看了不少书,但却很少有专项练习,因此开这样一个专题,希望能在练习中复习巩固所学的知识~ :)
函数篇(一)
本篇主要考察编写函数的技能和基本知识,同时也是对 JavaScript 标准库函数的练习。
1. 写一个函数用来反转数字
reverseNumber(12345); // 54321
2. 写一个函数来检测传入的字符串是否为回文
isPalindrome(''hello''); // false
isPalindrome(''madam''); // true
3. 写一个函数对传入的字符串输出所有子字符串组合(注意去重)
substrings(''dog''); // [''d'', ''do'', ''dog'', ''o'', ''og'', ''g'']
4. 写一个函数对传入的字符串重新按字母排序
reorderStr(''webmaster''); // abeemrstw
5. 写一个函数对传入的字符串中每个单词的首字母大写
upperWords(''the quick brown fox''); // The Quick Brown Fox
6. 写一个函数找出传入的字符串中最长的单词
findLongest(''Web Development Tutorial''); // Development
答案
以下给出我的解法,期待能有更好的答案。
// 1. 写一个函数用来反转数字
(function(){
''use strict'';
function reverseNumber(num) {
if(typeof num !== ''number'') {
throw "Pls input a number!";
}
var result = num.toString().split('''').reverse().join('''');
return +result;
}
console.log(reverseNumber(12345));
})();
// 2. 写一个函数来检测传入的字符串是否为回文
(function(){
''use strict'';
function isPalindrome(str) {
if(typeof str !== ''string'') {
throw "Pls input a string!";
}
var tmp = str.split('''').reverse().join('''');
return tmp === str;
}
console.log(isPalindrome(''hello''));
console.log(isPalindrome(''madam''));
})();
// 3. 写一个函数对传入的字符串输出所有子字符串组合
(function(){
''use strict'';
function substrings(str) {
if(typeof str !== ''string'') {
throw "Pls input a string!";
}
var result = [];
function next(idx) {
var i, n = str.length - idx;
for(i=1; i<=n; i++) {
add(str.substr(idx, i));
}
if(idx < str.length){
next(idx+1);
}
}
function add(item) {
if(result.indexOf(item)<0) {
result.push(item);
}
}
next(0);
return result;
}
console.log(substrings(''dog''));
})();
// 4. 写一个函数对传入的字符串重新按字母排序
(function(){
''use strict'';
function reorderStr(str) {
if(typeof str !== ''string'') {
throw "Pls input a string!";
}
return str.split('''').sort().join('''');
}
console.log(reorderStr(''webmaster''));
})();
// 5. 写一个函数对传入的字符串中每个单词的首字母大写
(function(){
''use strict'';
function upperWords(str) {
if(typeof str !== ''string'') {
throw "Pls input a string!";
}
return str.split('' '').map(upperFirstLetter).join('' '');
function upperFirstLetter(str) {
return str.charAt(0).toUpperCase().concat(str.substr(1));
}
}
console.log(upperWords(''the quick brown fox''));
})();
// 6. 写一个函数找出传入的字符串中最长的单词
(function(){
''use strict'';
function findLongest(str) {
if(typeof str !== ''string'') {
throw "Pls input a string!";
}
var items = str.split('' '');
return getMax(items);
function getMax(arr) {
var i, max = 0, n=arr.length;
for(i = 0; i < n; i++) {
if(arr[i].length > arr[max].length) {
max = i;
}
}
return arr[max];
}
}
console.log(findLongest(''Web Development Tutorial''));
})();
1+x 证书 Web 前端开发 HTML5 专项练习
官方QQ群
1+x 证书 Web 前端开发 HTML5 专项练习
2019 天梯赛练习题(L2 专项练习)
给定一个有 N 个顶点和 E 条边的无向图,请用 DFS 和 BFS 分别列出其所有的连通集。假设顶点从 0 到 N−1 编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入样例:
8 6
0 7
0 1
2 0
4 1
2 4
3 5
输出样例:
{ 0 1 4 2 7 } { 3 5 } { 6 } { 0 1 2 7 4 } { 3 5 } { 6 }
思路:先dfs,再bfs即可,但是注意在bfs之前要把vis数组再一次的初始化。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=15;
int n,m;
int a,b;
int ma[maxn][maxn];
bool vis[maxn];
vector<int>ans;
void dfs(int x)
{
if(vis[x])
return ;
vis[x]=true;
ans.push_back(x);
for(int i=0;i<n;i++)
{
if(ma[x][i])
dfs(i);
}
}
void bfs(int x)
{
if(vis[x])
return;
queue<int>q;
q.push(x);
ans.push_back(x);
vis[x]=true;
while(!q.empty())
{
int tem=q.front();
q.pop();
for(int i=0;i<n;i++)
{
if(ma[tem][i] && !vis[i])
{
q.push(i);
ans.push_back(i);
vis[i]=true;
}
}
}
}
int main()
{
cin>>n>>m;
memset(vis,false,sizeof(vis));
memset(ma,0,sizeof(ma));
while(m--)
{
cin>>a>>b;
ma[a][b]=ma[b][a]=1;
}
for(int i=0;i<n;i++)
{
ans.clear();
dfs(i);
int len=ans.size();
if(len!=0)
{
cout<<"{ ";
for(int j=0;j<len;j++)
cout<<ans[j]<<" ";
cout<<"}"<<endl;
}
}
memset(vis,false,sizeof(vis));
for(int i=0;i<n;i++)
{
ans.clear();
bfs(i);
int len=ans.size();
if(len!=0)
{
cout<<"{ ";
for(int j=0;j<len;j++)
cout<<ans[j]<<" ";
cout<<"}"<<endl;
}
}
return 0;
}
给定 N 个(长整型范围内的)整数,要求输出从小到大排序后的结果。
本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:
- 数据 1:只有 1 个元素;
- 数据 2:11 个不相同的整数,测试基本正确性;
- 数据 3:103 个随机整数;
- 数据 4:104 个随机整数;
- 数据 5:105 个随机整数;
- 数据 6:105 个顺序整数;
- 数据 7:105 个逆序整数;
- 数据 8:105 个基本有序的整数;
- 数据 9:105 个随机正整数,每个数字不超过 1000。
输入样例:
11
4 981 10 -17 0 -20 29 50 8 43 -5
输出样例:
-20 -17 -5 0 4 8 10 29 43 50 981
思路;可以选择一些nlogn 的排序算法去写,但是这题也可以水过去。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool cmp(const int &a,const int &b){
if(a < b)
return true;
return false;
}
int main()
{
int i,j,N,num;
vector<int> s;
vector<int>::iterator it;
cin>>N;
for(i=0;i<N;i++){
cin>>num;
s.push_back(num);
}
sort(s.begin(),s.end(),cmp);
for(it=s.begin();it!=s.end();it++){
if(it!=s.begin())
cout<<" ";
cout<<(*it);
}
return 0;
}
实现 QQ 新帐户申请和老帐户登陆的简化版功能。最大挑战是:据说现在的 QQ 号码已经有 10 位数了。
输入样例:
5
L 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
L 1234567890 myQQ@qq
L 1234567890 myQQ@qq.com
输出样例:
ERROR: Not Exist New: OK ERROR: Exist ERROR: Wrong PW Login: OK
思路:用map存储,然后到对应的情况就在map里面查询即可,不同的情况对应着不同的答案。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int maxn=10;
int n;
int a[maxn];
char c;
map<string,string>ma;
string s1,s2;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>c;
if(c==''L'')
{
cin>>s1>>s2;
if(ma.count(s1)==0)
cout<<"ERROR: Not Exist"<<endl;
else if(ma[s1]==s2)
cout<<"Login: OK"<<endl;
else
cout<<"ERROR: Wrong PW"<<endl;
}
else
{
cin>>s1>>s2;
if(ma.count(s1)==0)
{
cout<<"New: OK"<<endl;
ma[s1]=s2;
}
else
cout<<"ERROR: Exist"<<endl;
}
}
return 0;
}
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如 2+3*(7-4)+8/4
的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4
。请设计程序计算前缀表达式的结果值。
输入样例:
+ + 2 * 3 - 7 4 / 8 4
输出样例:
13.0
思路:了解前缀表达式的求值,先把字符串读入进来,然后从后往前,将读取出来的值放到stack 容器里面,如果读到操作符,就取出栈顶的两个元素进行运算,将运算的结果再存储到栈中。注意除数不能为0,以及最后的时候栈不能有数值了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=10;
int n;
string s;
stack<double>ss;
bool flag=0;
int main()
{
getline(cin,s);
int len=s.length();
double sum=0;
int t=1;
for(int i=len-1;i>=0;i--)
{
if(s[i]>=''0''&&s[i]<=''9'')
{
sum+=(s[i]-''0'')*t;
t*=10;
}
else if(s[i]==''.'')
{
sum=sum/(t*1.0);
t=1;
}
else if((s[i]==''+''||s[i]==''-'')&&sum!=0)
{
if(s[i]==''+'')
{
ss.push(sum);
i--;
continue;
}
else
{
ss.push(-sum);
i--;
continue;
}
}
else if(s[i]=='' '')
{
ss.push(sum);
sum=0;t=1;
continue;
}
else if(s[i]==''+'' || s[i]==''-'' || s[i]==''*'' || s[i]==''/'')
{
double a = ss.top();
ss.pop();
double b = ss.top();
ss.pop();
double tt = 0;
if(s[i] == ''+'')
tt = a+b;
else if(s[i] == ''-'')
tt = a-b;
else if(s[i] == ''*'')
tt = a*b;
else if(s[i] == ''/'')
{
if(b == 0)
{
flag = 1;
break;
}
tt = a/b;
}
ss.push(tt);
i--;
}
}
if(flag != 1)
printf("%.1lf\n",ss.top());
else
printf("ERROR\n");
return 0;
}
给定两个整数集合,它们的相似度定义为:/。其中 Nc是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。
输入样例:
3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3
输出样例:
50.00% 33.33%
思路:题意就是找到两个集合相同数值的数的个数,就可以用set 存储一个集合里面的元素,然后用一个set 里面的元素去匹配另一个set,得到相同数值的数的个数就可以了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
const int maxn=55;
int n,m,k,t;
int a,b;
set<int>s[maxn];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>m;
while(m--)
{
cin>>k;
s[i].insert(k);
}
}
cin>>m;
while(m--)
{
cin>>a>>b;
int sa=s[a].size();
int sb=s[b].size();
int same=0;
set<int>::iterator it;
for(it=s[a].begin();it!=s[a].end();it++)
{
if(s[b].find(*it)!=s[b].end())
same++;
}
double ans=same*1.0*100/(sa+sb-same);
printf("%.2f%%\n",ans);
}
return 0;
}
图着色问题是一个著名的 NP 完全问题。给定无向图 G=(V,E),问可否用 K 种颜色为 V 中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色?
但本题并不是要你解决这个着色问题,而是对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。
输入样例:
6 8 3
2 1
1 3
4 6
2 5
2 4
5 4
5 6
3 6
4
1 2 3 3 1 2
4 5 6 6 4 5
1 2 3 4 5 6
2 3 4 2 3 4
输出样例:
Yes Yes No No
思路:用二维数组ma[][]存储边,然后按给的颜色去查,如果边相同,且颜色相同就不满足题意。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn=505;
int n,m,k,q;
int ma[maxn][maxn];
int col[maxn];
set<int>s;
int main()
{
scanf("%d %d %d",&n,&m,&k);
memset(ma,0,sizeof(ma));
while(m--)
{
int a,b;
scanf("%d %d",&a,&b);
ma[a][b]=ma[b][a]=1;
}
scanf("%d",&q);
while(q--)
{
bool flag=false;
for(int i=1;i<=n;i++)
{
scanf("%d",&col[i]);
s.insert(col[i]);
}
if(s.size()!=k)
flag=true;
else
{
for(int i=1;i<=n&&!flag;i++)
{
for(int j=i+1;j<=n&&!flag;j++)
{
if(ma[i][j])
{
if(col[i]==col[j])
flag=true;
}
}
}
}
if(flag)
printf("No\n");
else
printf("Yes\n");
s.clear();
}
return 0;
}
给定一个最大容量为 M 的堆栈,将 N 个数字按 1, 2, 3, ..., N 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 M=5、N=7,则我们有可能得到 {1, 2, 3, 4, 5, 6, 7},但不可能得到 { 3, 2, 1, 7, 5, 6, 4 }。
输入样例:
5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2
输出样例:
YES NO NO YES NO
思路:就是走一遍存储的过程,用stack 去模拟出栈的情况,如果能够模拟成功就是YES,否则就是NO。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=1005;
stack<int>s;
queue<int>q;
int a[maxn];
int main()
{
int m,n,k;
cin>>m>>n>>k;
while(k--)
{
stack<int>s;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
int i=1,j=0;
while(s.size()<m && j<n)
{
s.push(i);//按开始的顺序push
i++;
while(!s.empty()&&j<n&&a[j]==s.top())//看给定的出栈顺序,相同则pop
{
j++;
s.pop();
}
if(i==n+1)
break;
}
if(i==n+1 && s.empty())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
当两台计算机双向连通的时候,文件是可以在两台机器间传输的。给定一套计算机网络,请你判断任意两台指定的计算机之间能否传输文件?
输入样例 1:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
输出样例 1:
no
no
yes
There are 2 components.
思路:并查集的简单应用,开始没看清题意,只有到最后的时候才需要判断联通集,并不需要在全联通的时候输出
The network is connected.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=10005;
int n;
int fa[maxn];
int cnt[maxn];
char c;
int a,b;
void init()
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
cnt[i]=1;
}
}
int findd(int x)
{
if(fa[x]==x)
return fa[x];
else
return fa[x]=findd(fa[x]);
}
void join(int x,int y)
{
int fx=findd(x),fy=findd(y);
if(fx!=fy)
{
fa[fx]=fy;
cnt[fy]+=cnt[fx];
cnt[fx]=0;
}
}
int main()
{
cin>>n;
init();
while(cin>>c)
{
if(c==''S'')
{
int sum=0;
for(int i=1;i<=n;i++)
{
if(cnt[i])
sum++;
}
if(sum==1)
printf("The network is connected.");
else
printf("There are %d components.\n",sum);
break;
}
else if(c==''C'')
{
cin>>a>>b;
if(findd(a)!=findd(b))
cout<<"no"<<endl;
else
cout<<"yes"<<endl;
}
else
{
cin>>a>>b;
join(a,b);
}
}
return 0;
}
著名的 “汉密尔顿(Hamilton)回路问题” 是要找一个能遍历图中所有顶点的简单回路(即每个顶点只访问 1 次)。本题就要求你判断任一给定的回路是否汉密尔顿回路。
输入样例:
6 10
6 2
3 4
1 5
2 5
3 1
4 1
1 6
6 3
1 2
4 5
6
7 5 1 4 3 6 2 5
6 5 1 4 3 6 2
9 6 2 1 6 3 4 5 2 6
4 1 2 5 1
7 6 1 3 4 5 2 6
7 6 1 2 5 4 3 1
输出样例:
YES
NO
NO
NO
YES
NO
思路:用二维数组ma[][]存边,然后按给的答案顺序判断,当点没访问过并且存在边的时候符合题意,否则就是NO
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=205;
int n,m,k;
int a,b;
int ma[maxn][maxn];
bool vis[maxn];
int aa[maxn];
int main()
{
memset(ma,0,sizeof(ma));
cin>>n>>m;
for(int i=1;i<=n;i++)
ma[i][i]=1;
while(m--)
{
cin>>a>>b;
ma[a][b]=ma[b][a]=1;
}
cin>>m;
while(m--)
{
memset(vis,false,sizeof(vis));
cin>>k;
for(int i=1;i<=k;i++)
cin>>aa[i];
if(k!=n+1)
cout<<"NO"<<endl;
else if(aa[1]!=aa[k])
cout<<"NO"<<endl;
else
{
int flag=1;
vis[aa[1]]=true;
for(int i=2;i<k;i++)
{
if(vis[aa[i]] || !ma[aa[i-1]][aa[i]])
{
flag=0;
break;
}
vis[aa[i]]=true;
}
if(!ma[aa[k-1]][aa[k]])
flag=0;
if(flag)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}
将 {0, 1, 2, ..., N-1} 的任意一个排列进行排序并不困难,这里加一点难度,要求你只能通过一系列的 Swap (0, *) —— 即将一个数字与 0 交换 —— 的操作,将初始序列增序排列。例如对于初始序列 { 4, 0, 2, 1, 3 },我们可以通过下列操作完成排序:
- Swap(0, 1) ⟹ { 4, 1, 2, 0, 3 }
- Swap(0, 3) ⟹ { 4, 1, 2, 3, 0 }
- Swap(0, 4) ⟹ { 0, 1, 2, 3, 4 }
本题要求你找出将前 N 个非负整数的给定排列进行增序排序所需要的最少的与 0 交换的次数。
输入样例:
10
3 5 7 2 6 4 9 0 8 1
输出样例:
9
思路:找循环节。(3,0,7,2),(5,1,9,6,4),(8)三个
第一个节(包含0)需要循环节长度-1次操作,即可把其它元素移到对应的位置
第二个节(不包含0)需要循环节长度+1次操作,可以看成向循环节中加入0(操作次数加1),
那么循环节长度加1(交换时次数要加1),总共比包含0的情况多操作两次
第三个节是一个元素,那么不需要任何操作。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=100005;
int n;
int a[maxn],b[maxn];
int vis[maxn];
map<int,int>ma;
void dfs(int x,int t)
{
if(vis[x])
return ;
vis[x]=t;
dfs(b[x],t);
}
int main()
{
memset(vis,0,sizeof(vis));
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
b[a[i]]=i;
}
int cnt=1;
for(int i=0;i<n;i++)
{
if(!vis[i])
{
dfs(a[i],cnt);
cnt++;
}
}
for(int i=0;i<n;i++)
ma[vis[i]]++;
int ans=0;
for(int i=1;i<cnt;i++)
{
if(ma[i]==1)
continue;
if(i==vis[0])
ans+=ma[i]-1;
else
ans+=ma[i]+1;
}
printf("%d\n",ans);
return 0;
}
GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function
持续更新 Go 语言学习进度中 ......
2023-03-14 GO 语言学习笔记 系列部分 已完结!!
对于刚刚接触 golang 来说,经过这段时间的学习,对于 GO 这门语言已经有了初步的认识。
博主接下来会继续学习 golang 的更多内容,持续更新中......
-
- GO 语言学习笔记 - 类型篇 Study for Go! Chapter one - Type
- GO 语言学习笔记 - 表达式篇 Study for Go ! Chapter two - Expression
- GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function
- GO 语言学习笔记 - 数据篇 Study for Go ! Chapter four - Data
- GO 语言学习笔记 - 方法篇 Study for Go ! Chapter five - Method
- GO 语言学习笔记 - 接口篇 Study for Go ! Chapter six - Interface
- GO 语言学习笔记 - 并发篇 Study for Go ! Chapter seven - Concurrency
- GO 语言学习笔记 - 包结构篇 Study for Go ! Chapter eight - Package Structure
- GO 语言学习笔记 - 反射篇 Study for Go ! Chapter nine - Reflect
- GO 语言学习笔记 - 测试篇 Study for Go ! Chapter ten- Test
- GO 语言学习笔记 - 工具链篇 Study for Go ! Chapter eleven - Tool Chain
Study for Go ! Chapter three - Function
-
Initialization
-
函数是结构化编程的最小模块单元
-
函数是代码复用和测试的基本单元
-
关键字 func
-
无需前置声明
-
不支持命名嵌套定义 (nested)
-
不支持同名函数重载 (overload)
-
不支持默认参数
-
支持不定长变参
-
支持多返回值
-
支持命名返回值
-
支持匿名函数和闭包
-
花括号不能另起一行
-
函数属于第一类对象,具备相同签名(参数和返回值列表)的视作同一类型
First-class object:指可在运行期创建,可用作函数参数或返回值,可存入变量的实体。最常见的用法是匿名函数
-
从阅读和代码的维护角度来说,使用命名类型更加方便
-
函数只能判断其是否为 nil,不支持其他比较操作
-
从函数返回局部变量指针是安全的,编译器会通过逃逸分析( escape analysis ) 来决定是否在堆上分配内存
-
函数内联(inline)对内存分配有一定的影响。
-
编译器可能未实现尾递归优化 (tail-call optimization)尽管 golang 执行栈的上线是 GB 规模,轻易不会出现堆栈溢出 (stack overflow)错误,但是依然余姚注意拷贝栈的复制成本
Notice:(name rule)
-
在避免冲突的情况下,函数命名要本着精简短小,望文知意的原则
-
通常是动词和介词加上名词,例如:scanWords
-
避免不必要的缩写,printError 比 printErr 更好
-
避免使用类型关键字,比如 buildUserStruct 就会看起来别扭
-
避免歧义,不能有多种用途的解释造成误解
-
避免只能通过大小写区分的同名函数
-
避免与内置函数同名,这会导致误用
-
避免使用数字,除非是特定专有名词 如 UTF8
-
避免添加作用域提示前缀
-
同一使用 camel /pascal case 拼写风格
-
使用相同术语,保持一致性
-
使用习惯用语,比如 init 表示初始化, is /has 返回布尔值结果
-
使用反义词组命名行为相反的函数,比如: get /set, min /max 等
Attention:
-
函数和方法的命名规则有些不同,方法通过选择符调用,且具备状态上下文,可使用更简短的动词命名
-
-
argument
-
Go 对参数的处理偏向保守,不支持有默认值的可选参数
-
不支持命名实参
-
调用时必须按签名顺序传递指定类型和数量的实参,就算以 “_” 命名的参数也不能忽略
-
在参数列表中,相邻的同类型参数可以合并
-
参数可以被视作函数局部变量,因此不能再相同层次定义同名变量
-
形参是指函数定义中的参数,实参则是函数调用时所传递的参数。形参类似函数局部变量,而实参则是函数外部对象,可以是常量、变量、表达式或者函数等
-
不管是指针,引用类型,还是其他类型参数,都是值拷贝传递 (pass-by-value)区别无非是拷贝目标对象,还是拷贝指针而已。
-
在函数调用前,会为形参和返回值分配内存空间,并将实参拷贝到形参内存
-
尽管实参和形参都指向同一目标,但传递指针时依然被复制
Attention:
-
表面上看,指针参数的性能可能更好一些,但是实际上需要具体分析,被复制的指针会延长目标对象生命周期,还可能会导致它被分配到堆上,那么其性能消耗就得加上堆内存分配和垃圾回收的成本
-
其实在栈上复制小对象只需很少的指令就可完成,远比运行时进行堆的内存分配要快得多,另外并发编程也提倡尽可能使用不可变对象 (只读或复制),这可以消除数据同步等麻烦。当然如果复制成本很高,或者需要修改原对象状态,自然使用指针更好
-
要使用传出参数 (out) 通常建议使用返回值,当然也可以使用二级指针
-
如果函数参数过多,建议将其重构为一个符合结构类型,也算是变相实现可选参数和命名实参等功能,例如:将过多的参数独立成 option struct , 既便于扩展参数集,也方便通过 newOption 函数设置默认配置,这也是代码复用的一种方式,避免多处调用时的繁琐的参数配置
变参:
-
变参实际上本质是一个切片,只能接受一到多个同类型参数,且必须放在列表尾部
-
将切片作为变参时,须进行展开操作,如果是数组,先将其转换为切片
-
参数复制的仅是切片自身,并不包括底层数组,也因此可修改原数据,如果需要,可用内置函数 copy 复制底层数据
-
return
-
有返回值的函数,必须有明确的 return 终止语句
-
除非有 panic,或者无 break 的死循环,则无须 return 终止语句
-
借鉴自动态语言的多返回值模式,函数得以返回更多状态,尤其是 error 模式
-
golang 中稍有不便的是没有元组(tuple)类型,也不能用数组、切片接受,但可用 “_” 忽略掉不想要的返回值
-
多返回值可以用作其他函数调用实参,或当作结果直接返回
-
在 golang 中命名返回值和简短变量定义 一样,既有优点也有缺点
-
命名返回值让函数声明更加清晰,同时也会改善帮助文档和代码编辑器提示
-
命名返回值和参数一样,可当作函数局部变量使用,最后由 return 隐式返回
-
这种特殊的 “局部变量” 会被不同层级的同名变量遮蔽。 但编译器能检查到此类情况,只要改为显式 return 返回即可
-
除遮蔽外,我们还需要对全部返回值命名,否则编译器会搞不清状况
-
如果返回值能明确表明其含义,就尽量不要对其命名
-
匿名函数 anonymous function
-
匿名函数 是指没有定义名字符号的函数
-
除了没有名字以外,匿名函数和普通函数完全相同。最大的区别是,我们可以在函数内部定义匿名函数,形成类似 嵌套效果。匿名函数可以直接调用,保存到变脸,作为参数或返回值
-
将匿名函数赋值给变量,与为普通函数提供名字标识符有着根本的区别。当然,编译器会为匿名函数生成一个 “随机” 符号名
-
普通函数 与 匿名函数都可以作为结构体字段,或经过通道传递
-
不曾使用的匿名函数会被编译器当作错误
-
除闭包因素外,匿名函数也是一种常见的重构手段,可以将大函数分解成多个相对独立的匿名函数块,然后用相对简洁的调用完成逻辑流程,以实现框架和细节
-
相比语句块,匿名函数的作用域被隔离(不使用闭包),不会引发外部污染,更加灵活。没有定义顺序限制,必要时可抽离,便于实现干净、清晰的代码层次
closure 闭包
-
closure 是在其词法上下文中引用了自由变量的函数,或者说是函数及其引用的环境的组合体
-
正因为闭包通过指针引用环境变量,那么可能会导致其生命周期延长,甚至被分配到堆内存。另外。还有所谓的 “延迟求值” 的特性
-
多个匿名函数引用同一环境变量,也会让事情变得复杂,任何修改行为都会影响其他函数取值,在并发模式下可能需要做同步处理
-
闭包让我们不用传递参数就可以读取或修改环境状态,当然也要为此付出格外代价,对于性能要求较高的场合,须谨慎使用
-
延迟调用 delayed call
-
语句 defer 向当前函数注册稍后执行的函数调用。这些调用就被称作延迟调用,因为它们直到当前函数执行结束前才被执行
-
常用于资源释放接触锁定,以及错误处理 等操作
Attention:
-
延迟调用注册的是调用,必须提供执行所需参数(即使是空),参数在注册时被复制并缓存起来,如果对状态敏感,可改用指针或闭包
-
延迟调用可修改当前函数命名返回值,但自身返回值被抛弃
-
多个延迟注册按 FLFO 次序执行
-
延迟调用要在函数结束时才被执行,不合理的使用方式会浪费更多资源,甚至造成逻辑错误
-
相比直接用 CALL 汇编指令调用函数,延迟调用需要花费更大的代价,这其中包括 注册、调用等操作,还有格外的缓存开销,所以追求性能的算法应避免使用延迟调用
-
错误处理
-
golang 的错误处理与目前流行的趋势背道而驰
-
官方推荐的标准是 返回 error 状态
-
标准库将 error 定义为接口类型, 以便实现自定义错误类型
-
按照惯例, error 总是最后一个返回参数,标准库提供看相关创建函数,可以方便地创建包含简单错误文本的 error 对象
-
应从错误变量 而不是文本内容来判定错误类别
-
错误变量通常 以 err 作为前缀、且自负床内容全部小写,没有结束标点。以便于嵌入到其他格式化字符串中输出
-
全局错误变量并非没有问题,因为它们可以被用户重新赋值,这就可能导致结果不匹配,不知道以后是否会出现 只读变量功能,否则就只能靠自觉 了
-
与 error.New 类似的还有 fmt.Errorf , 它返回一个格式化无内容的错误对象
-
某些时候,我们需要自定义错误类型,以容纳更多上下文状态信息。
-
在正式代码中,我们不能忽略 error 返回值,应严格检查,否则可能导致错误的逻辑状态。调用多返回值函数时,除了 error 外,其他返回值同样需要关注
Notice:如何解决大量函数和方法返回 error 使得调用代码变得很难看的问题
-
使用专门的检查函数处理错误逻辑(比如记录日志), 简化检查代码
-
在不影响逻辑的情况下,使用 defer 延后处理错误状态(err 退化赋值)
-
在不中断逻辑的情况下,将错误作为内部状态报错,等最终 “提交” 时再处理
-
panic,recover
-
与 error 相比,panic/recover 再使用方法上更接近 try/catch 结构化异常
-
它们都是内部函数而非语句
-
panic 会立即中断当前函数流程,执行延迟调用
-
而 recove r 在延迟调用函数中 可捕获并返回 panic 提交的错误对象
-
因为 panic 参数时空接口类型, 因此可使用任何对象作为错误标志。而 recover 返回结果同样需要转型才能获得具体信息
-
无论是否执行 recover,所有延迟调用都会被执行,但中断性错误会沿调用堆栈向外传递,要么被外场捕获,要么导致进程崩溃
-
recover 必须在延迟调用函数中执行才能正常工作
-
除非是不可恢复性、导致系统无法正常工作的错误,否则不建议使用 panic
Javascript 与 CSS,JavaScript 的动态加载技术
动态加载 css
var dynamicLoading = {
css: function(path){
if(!path || path.length === 0){
throw new Error(''argument "path" is required !'');
}
var head = document.getElementsByTagName(''head'')[0];
var link = document.createElement(''link'');
link.href = path;
link.rel = ''stylesheet'';
link.type = ''text/css'';
head.appendChild(link);
},
js: function(path){
if(!path || path.length === 0){
throw new Error(''argument "path" is required !'');
}
var head = document.getElementsByTagName(''head'')[0];
var script = document.createElement(''script'');
script.src = path;
script.type = ''text/javascript'';
head.appendChild(script);
}
}
动态加载 js
<script>
var oHead = document.getElementsByTagName(''HEAD'').item(0);
var oScript= document.createElement("script");
oScript.type = "text/javascript";
oScript.src="test.js";
oHead.appendChild( oScript);
</script>
Webkit 浏览器滚动条设置
::-webkit-scrollbar
{
width: 10px;
height: 6px;
}
::-webkit-scrollbar-track-piece
{
background-color: #CCCCCC;
-webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:vertical
{
height: 5px;
background-color: #999999;
-webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:horizontal
{
width: 5px;
background-color: #CCCCCC;
-webkit-border-radius: 6px;
}
::-webkit-scrollbar-track-piece {
background-color: transparent;
}
body::-webkit-scrollbar-track-piece {
background-color: white;
}
::-webkit-scrollbar-track-piece:no-button {}
::-webkit-scrollbar-thumb {
background-color: #3994EF;
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background-color: #A4EEF0;
}
::-webkit-scrollbar-thumb:active {
background-color: #666;
}
::-webkit-scrollbar-button:vertical { width: 9px; }
::-webkit-scrollbar-button:horizontal { width: 9px; }
::-webkit-scrollbar-button:vertical:start:decrement { background-color: white; }
::-webkit-scrollbar-button:vertical:end:increment { background-color: white; }
::-webkit-scrollbar-button:horizontal:start:decrement { background-color: white; }
::-webkit-scrollbar-button:horizontal:end:increment { background-color: white; }
http://www.lyblog.net/2013/314.html
-------------------- 盾牌形状 ----------------------
padding-top: 20px;
border-raduis:12px;
border: 2px solid #fff;
今天关于JavaScript 专项练习:函数篇和一的分享就到这里,希望大家有所收获,若想了解更多关于1+x 证书 Web 前端开发 HTML5 专项练习、2019 天梯赛练习题(L2 专项练习)、GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function、Javascript 与 CSS,JavaScript 的动态加载技术等相关知识,可以在本站进行查询。
本文标签: