GVKun编程网logo

JavaScript 专项练习:函数篇(一)(javascript函数题)

3

本文将介绍JavaScript专项练习:函数篇的详细情况,特别是关于一的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于1+x证书Web前端开发HTM

本文将介绍JavaScript 专项练习:函数篇的详细情况,特别是关于的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于1+x 证书 Web 前端开发 HTML5 专项练习、2019 天梯赛练习题(L2 专项练习)、GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function、Javascript 与 CSS,JavaScript 的动态加载技术的知识。

本文目录一览:

JavaScript 专项练习:函数篇(一)(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 专项练习

1+x 证书 Web 前端开发 HTML5 专项练习

官方QQ群

1+x 证书 Web 前端开发 HTML5 专项练习
http://blog.zh66.club/index.php/archives/193/

2019 天梯赛练习题(L2 专项练习)

2019 天梯赛练习题(L2 专项练习)

7-2 列出连通集 (25 分)

给定一个有 N 个顶点和 E 条边的无向图,请用 DFS 和 BFS 分别列出其所有的连通集。假设顶点从 0 到 N1 编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入样例:

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;
}
7-3 排序 (25 分)

给定 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;
}
7-4 QQ 帐户的申请与登陆 (25 分)

实现 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;
}
7-5 求前缀表达式的值 (25 分)

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如 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;
}
7-8 集合相似度 (25 分)

给定两个整数集合,它们的相似度定义为:/。其中 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;
}
7-9 图着色问题 (25 分)

图着色问题是一个著名的 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;
}
7-10 出栈序列的合法性 (25 分)

给定一个最大容量为 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;
}
7-11 文件传输 (25 分)

当两台计算机双向连通的时候,文件是可以在两台机器间传输的。给定一套计算机网络,请你判断任意两台指定的计算机之间能否传输文件?

输入样例 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;
}
7-12 汉密尔顿回路 (25 分)

著名的 “汉密尔顿(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;
}
7-14 与零交换 (25 分)

将 {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 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function

持续更新 Go 语言学习进度中 ......

2023-03-14 GO 语言学习笔记 系列部分 已完结!!

对于刚刚接触 golang 来说,经过这段时间的学习,对于 GO 这门语言已经有了初步的认识。

博主接下来会继续学习 golang 的更多内容,持续更新中......

    1. GO 语言学习笔记 - 类型篇 Study for Go! Chapter one - Type
    2. GO 语言学习笔记 - 表达式篇 Study for Go ! Chapter two - Expression
    3. GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function 
    4. GO 语言学习笔记 - 数据篇 Study for Go ! Chapter four - Data
    5. GO 语言学习笔记 - 方法篇 Study for Go !  Chapter five - Method
    6. GO 语言学习笔记 - 接口篇 Study for Go ! Chapter six - Interface
    7. GO 语言学习笔记 - 并发篇 Study for Go !  Chapter seven - Concurrency
    8. GO 语言学习笔记 - 包结构篇 Study for Go !  Chapter eight - Package Structure
    9. GO 语言学习笔记 - 反射篇 Study for Go ! Chapter nine - Reflect
    10. GO 语言学习笔记 - 测试篇 Study for Go ! Chapter ten- Test
    11. GO 语言学习笔记 - 工具链篇 Study for Go !  Chapter eleven - Tool Chain

 

Study for Go ! Chapter three - Function

  1. 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:

    • 函数和方法的命名规则有些不同,方法通过选择符调用,且具备状态上下文,可使用更简短的动词命名

 

  1. argument

  • Go 对参数的处理偏向保守,不支持有默认值的可选参数

  • 不支持命名实参

  • 调用时必须按签名顺序传递指定类型和数量的实参,就算以 “_” 命名的参数也不能忽略

  • 在参数列表中,相邻的同类型参数可以合并

  • 参数可以被视作函数局部变量,因此不能再相同层次定义同名变量

  • 形参是指函数定义中的参数,实参则是函数调用时所传递的参数。形参类似函数局部变量,而实参则是函数外部对象,可以是常量、变量、表达式或者函数等

  • 不管是指针,引用类型,还是其他类型参数,都是值拷贝传递 (pass-by-value)区别无非是拷贝目标对象,还是拷贝指针而已。

  • 在函数调用前,会为形参和返回值分配内存空间,并将实参拷贝到形参内存

  • 尽管实参和形参都指向同一目标,但传递指针时依然被复制

 

Attention:

  1. 表面上看,指针参数的性能可能更好一些,但是实际上需要具体分析,被复制的指针会延长目标对象生命周期,还可能会导致它被分配到堆上,那么其性能消耗就得加上堆内存分配和垃圾回收的成本

  2. 其实在栈上复制小对象只需很少的指令就可完成,远比运行时进行堆的内存分配要快得多,另外并发编程也提倡尽可能使用不可变对象 (只读或复制),这可以消除数据同步等麻烦。当然如果复制成本很高,或者需要修改原对象状态,自然使用指针更好

 

  • 要使用传出参数 (out) 通常建议使用返回值,当然也可以使用二级指针

  • 如果函数参数过多,建议将其重构为一个符合结构类型,也算是变相实现可选参数和命名实参等功能,例如:将过多的参数独立成 option struct , 既便于扩展参数集,也方便通过 newOption 函数设置默认配置,这也是代码复用的一种方式,避免多处调用时的繁琐的参数配置 

 

 

 

变参:

  • 变参实际上本质是一个切片,只能接受一到多个同类型参数,且必须放在列表尾部

  • 将切片作为变参时,须进行展开操作,如果是数组,先将其转换为切片

  • 参数复制的仅是切片自身,并不包括底层数组,也因此可修改原数据,如果需要,可用内置函数 copy 复制底层数据

 

  1. return

  • 有返回值的函数,必须有明确的 return 终止语句

  • 除非有 panic,或者无 break 的死循环,则无须 return 终止语句

  • 借鉴自动态语言的多返回值模式,函数得以返回更多状态,尤其是 error 模式

  • golang 中稍有不便的是没有元组(tuple)类型,也不能用数组、切片接受,但可用 “_” 忽略掉不想要的返回值

  • 多返回值可以用作其他函数调用实参,或当作结果直接返回

  • 在 golang 中命名返回值和简短变量定义 一样,既有优点也有缺点

  • 命名返回值让函数声明更加清晰,同时也会改善帮助文档和代码编辑器提示

  • 命名返回值和参数一样,可当作函数局部变量使用,最后由 return 隐式返回

  • 这种特殊的 “局部变量” 会被不同层级的同名变量遮蔽。 但编译器能检查到此类情况,只要改为显式 return 返回即可

  • 除遮蔽外,我们还需要对全部返回值命名,否则编译器会搞不清状况

  • 如果返回值能明确表明其含义,就尽量不要对其命名

 

  1. 匿名函数 anonymous function

  • 匿名函数 是指没有定义名字符号的函数

  • 除了没有名字以外,匿名函数和普通函数完全相同。最大的区别是,我们可以在函数内部定义匿名函数,形成类似 嵌套效果。匿名函数可以直接调用,保存到变脸,作为参数或返回值

  • 将匿名函数赋值给变量,与为普通函数提供名字标识符有着根本的区别。当然,编译器会为匿名函数生成一个 “随机” 符号名

  • 普通函数 与 匿名函数都可以作为结构体字段,或经过通道传递

  • 不曾使用的匿名函数会被编译器当作错误

  • 除闭包因素外,匿名函数也是一种常见的重构手段,可以将大函数分解成多个相对独立的匿名函数块,然后用相对简洁的调用完成逻辑流程,以实现框架和细节

  • 相比语句块,匿名函数的作用域被隔离(不使用闭包),不会引发外部污染,更加灵活。没有定义顺序限制,必要时可抽离,便于实现干净、清晰的代码层次

 

closure 闭包

  • closure 是在其词法上下文中引用了自由变量的函数,或者说是函数及其引用的环境的组合体

  • 正因为闭包通过指针引用环境变量,那么可能会导致其生命周期延长,甚至被分配到堆内存。另外。还有所谓的 “延迟求值” 的特性

  • 多个匿名函数引用同一环境变量,也会让事情变得复杂,任何修改行为都会影响其他函数取值,在并发模式下可能需要做同步处理

  • 闭包让我们不用传递参数就可以读取或修改环境状态,当然也要为此付出格外代价,对于性能要求较高的场合,须谨慎使用

 

  1. 延迟调用 delayed call

  • 语句 defer 向当前函数注册稍后执行的函数调用。这些调用就被称作延迟调用,因为它们直到当前函数执行结束前才被执行

  • 常用于资源释放接触锁定,以及错误处理 等操作

 

Attention:

  1. 延迟调用注册的是调用,必须提供执行所需参数(即使是空),参数在注册时被复制并缓存起来,如果对状态敏感,可改用指针或闭包

 

  • 延迟调用可修改当前函数命名返回值,但自身返回值被抛弃

  • 多个延迟注册按 FLFO 次序执行

  • 延迟调用要在函数结束时才被执行,不合理的使用方式会浪费更多资源,甚至造成逻辑错误

  • 相比直接用 CALL 汇编指令调用函数,延迟调用需要花费更大的代价,这其中包括 注册、调用等操作,还有格外的缓存开销,所以追求性能的算法应避免使用延迟调用

 

  1. 错误处理

  • golang 的错误处理与目前流行的趋势背道而驰

  • 官方推荐的标准是 返回 error 状态

  • 标准库将 error 定义为接口类型, 以便实现自定义错误类型

  • 按照惯例, error 总是最后一个返回参数,标准库提供看相关创建函数,可以方便地创建包含简单错误文本的 error 对象

  • 应从错误变量 而不是文本内容来判定错误类别

  • 错误变量通常 以 err 作为前缀、且自负床内容全部小写,没有结束标点。以便于嵌入到其他格式化字符串中输出

  • 全局错误变量并非没有问题,因为它们可以被用户重新赋值,这就可能导致结果不匹配,不知道以后是否会出现 只读变量功能,否则就只能靠自觉 了

  • 与 error.New 类似的还有 fmt.Errorf , 它返回一个格式化无内容的错误对象

  • 某些时候,我们需要自定义错误类型,以容纳更多上下文状态信息。

  • 在正式代码中,我们不能忽略 error 返回值,应严格检查,否则可能导致错误的逻辑状态。调用多返回值函数时,除了 error 外,其他返回值同样需要关注

 

Notice:如何解决大量函数和方法返回 error 使得调用代码变得很难看的问题

  1. 使用专门的检查函数处理错误逻辑(比如记录日志), 简化检查代码

  2. 在不影响逻辑的情况下,使用 defer 延后处理错误状态(err 退化赋值)

  3. 在不中断逻辑的情况下,将错误作为内部状态报错,等最终 “提交” 时再处理

 

  • panic,recover

  • 与 error 相比,panic/recover 再使用方法上更接近 try/catch 结构化异常

  • 它们都是内部函数而非语句

  • panic 会立即中断当前函数流程,执行延迟调用

  • 而 recove r 在延迟调用函数中 可捕获并返回 panic 提交的错误对象

  • 因为 panic 参数时空接口类型, 因此可使用任何对象作为错误标志。而 recover 返回结果同样需要转型才能获得具体信息

  • 无论是否执行 recover,所有延迟调用都会被执行,但中断性错误会沿调用堆栈向外传递,要么被外场捕获,要么导致进程崩溃

  • recover 必须在延迟调用函数中执行才能正常工作

  • 除非是不可恢复性、导致系统无法正常工作的错误,否则不建议使用 panic

Javascript 与 CSS,JavaScript 的动态加载技术

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
{
    width10px;
    height6px;
}
::-webkit-scrollbar-track-piece
{
    background-color#CCCCCC;
    -webkit-border-radius6px;
}
::-webkit-scrollbar-thumb:vertical
{
    height5px;
    background-color#999999;
    -webkit-border-radius6px;
}
::-webkit-scrollbar-thumb:horizontal
{
    width5px;
    background-color#CCCCCC;
    -webkit-border-radius6px;
}

::-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-radius3px;
}

::-webkit-scrollbar-thumb:hover {
  background-color#A4EEF0;
}

::-webkit-scrollbar-thumb:active {
  background-color#666;
}

::-webkit-scrollbar-button:vertical { width9px; }
::-webkit-scrollbar-button:horizontal { width9px; }
::-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-top20px;
border-raduis:12px;
border2px solid #fff;

今天关于JavaScript 专项练习:函数篇的分享就到这里,希望大家有所收获,若想了解更多关于1+x 证书 Web 前端开发 HTML5 专项练习、2019 天梯赛练习题(L2 专项练习)、GO 语言学习笔记 - 函数篇 Study for Go ! Chapter three - Function、Javascript 与 CSS,JavaScript 的动态加载技术等相关知识,可以在本站进行查询。

本文标签: