第三章 Hodgepodge: 构建可拓展的JavaScript库

第三章 Hodgepodge: 构建可拓展的JavaScript库

  • 3.2 全面的代码组织
    • 1. 怎样组织Javascript代码来避免命名冲突,并将相关函数干净地分组在一起?
    • 2.
    • 3. 如何在警告包里加一个类?比如展示特定信息。
    • 4. something about import
  • 3.3 创建包
    • 3.3.1 构建jscript.array包
      • 1. 如何将一个数组的内容复制到另一个数组
      • 2. 怎样在一个数组中查找指定的元素
      • 3. 假设我有一个数值的数组,如何计算数组中所有元素的平均值?
    • 3.3.2 构建jscript.browser包
      • 如何获取正在使用应用程序的浏览器的标识信息?
    • 3.3.3 构建jscript.datetime包
      • 1. 怎样知道一个给定月有多少天?
      • 2.怎样判断给定的年份是否为闰年
    • 3.3.4 构建jscript.debug包
      • 1.如何显示任意的一个对象的所有属性及它们的值呢?
      • 2.如何实现一个健壮的自动记录日志机制呢,类似于Jakarta Commons Logging?
    • 3.3.5 构建jscript.dom包
      • 1.如何将任意一个DOM元素居中
      • 2. 如何竖直居中?
      • 3.当使用一个Ajax请求时,得到一堆返回的内容。如果那堆内容中包含一些< script >段,如何执行?
      • 4. 如何引用任意数量的DOM?
    • 3.3.6 构建jscript.form包
      • 1. 如何从一个HTML表单生成XML?
      • 2.如何在< select>域里查找并随意选择一个指定的选项?
      • 3.如何在一个< select>中提供全选功能?
    • 3.3.7 构建jscript.lang包
      • 如何获得一个对象的属性并把它们复制给另一个对象?
    • 3.3.8 构建jscript.math包
      • 如何在一个指定范围内生成随机数?
    • 3.3.9 构建jscript.page包
      • 1.如何用程序启动对当前页面的打印?
      • 2.如何使用一个传入页面的参数呢?
      • 3.如何使用JavaScript打破一个框架?
    • 3.3.10 构建jscript.storage包
      • 1.如何创建一个cookie并把它保存在客户端呢?
      • 2.如何获得一个指定cookie的值呢?
      • 3.如何删除cookie?
    • 3.3.11 构建jscript.string包
      • 1.如何计算一个子串在字符串中出现的次数?
      • 2.如何从字符串删除指定的字母?或从字符串中删除除了指定字母之外的其他任何字母?
      • 3.如果不想改变字符串,只是测试一下是否只包含而合法字符或者只包含非法字符,怎么做?
      • 4.如何在一个字符串中替换出现的所有某个子串?
      • 5.如何从字符串的开头删掉空格?(左侧,右侧,左右两侧)
      • 6.怎样把一个字符串分割成几个指定长度的片段?
  • 小结

3.2 全面的代码组织

1. 怎样组织Javascript代码来避免命名冲突,并将相关函数干净地分组在一起?

在JavaScript中,你可以在某种程度上效仿在Java,C#或其他现代语言中使用的包系统。所有你需要做的就是创建一个新的类,然后将所有工具函数作为那个类的成员。

2.

var v = new jscript.ui.alerts();

在java中不行,但在JavaScript中可以,每个函数都是一个类的构造函数,不是创建实例的机制。

jscript = new function(){
  return null;
}
var v = new jscript();

v的值为null吗?不。null是jscript所指向的那个函数返回的,而不是那个函数被执行的结果。

3. 如何在警告包里加一个类?比如展示特定信息。

jascript.ui.alerts.MessageDisplayer = function(inMsg){
   this.msg = inMsg;
   this.toString = function(){
     return "msg=" + this.msg;
   }
}
var v= new jscript.ui.alerts.MessageDisplayer("Hello!");
alert(v);

这样实际上是在jascript.ui.alerts包中创建了一个名为MessageDisplayer的类。执行到最后两行,创建新的MessageDisplayer的实例,“Hello!”被传给构造函数。当调用alert( ),并传递指向那个实例的变量时,就会调用toString( )函数,我们得到预期结果:弹出信息:“msg=Hello!”。

4. something about import

假设我们想有个叫jsctipt.string的包,希望把这个独立包输入到代码中,可创建这样的文件:

iftypeof jscript == 'undefined'{
  jscript = function(){ }
}
jscript.string = function(){ }

jscript.string.sampleFunction = function(inMsg){
  alert(inMsg);
}

为把这些“导入”一个页面:

<script src="jscript.string.js"></script>

(1)如果这是唯一的导入,那么我们就得到一个jscript对象,它包含一个字符串函数,这个字符串函数最后包含sampleFunction函数,所有这些都是在一个层级关系中,最后组成伪包。
(2)更好的做法,如果jscript下面有另外的包,并且我们要导入它们,那么这儿用的if检查语句可以确保每一个包对象总是只有一个副本。
(3)一个最终的好处:如果后来想要扩展包,比如,添加一个jscript.string.format包,我们需要做的就是添加一个新的jscript.string.format.js文件,使用同样的检查方法,再添加一个来检查jscript.string是否已经被定义,如果没有定义就实例化。
(4)目前,用通配符导入足够了,但也可拥有特定类导入的功能:每个单独的包中的每个函数或每个对象放在它自己的.js文件中。

3.3 创建包

3.3.1 构建jscript.array包

1. 如何将一个数组的内容复制到另一个数组

/**
 * Copies inSrcArray into inDestArray, appending all the values from inSrcArray
 * onto inDestArray.
 *
 * @param inSrcArray  The array to copy FROM.
 * @param inDestArray The array to copy TO.
 * @return            The destination array with the copied elements from the
 *                    source array.
 */
jscript.array.copyArray = function(inSrcArray, inDestArray) {

  var i;
  for (i = 0; i < inSrcArray.length; i++) {
    inDestArray.push(inSrcArray[i]);
  }
  return inDestArray;

} // End copyArray().

2. 怎样在一个数组中查找指定的元素

/**
 * Finds a specified value in an array and returns its position, or -1 if
 * the value is not found.
 *
 * @param  inArray The array to search.
 * @param  inValue The value to look for.  Note that the value is search for
 *                 EXACTLY, i.e., case matters, as does whitespace.
 * @return         The array position the match is found, or -1 if not found.
 */
jscript.array.findInArray = function(inArray, inValue) {

  var i;
  for (i = 0; i < inArray.length; i++) {
    if (inArray[i] == inValue) {
      return i;
    }
  }
  return -1;//没查找到的常见返回值

} // End findInArray().

3. 假设我有一个数值的数组,如何计算数组中所有元素的平均值?

/**
 * Calculates the average of an array of numeric values.  Note that any
 * element in the array that is not numeric will likely fowl things up, and
 * this IS NOT checked for.  It is the caller's responsibility to ensure
 * the array contains only numeric values!
 *
 * @param inArray The array of ONLY numeric values to average.
 */
jscript.array.arrayAverage = function(inArray) {

  var accumulator = 0;
  var i;
  for (i = 0; i < inArray.length; i++) {
    accumulator += inArray[i];
  }
  return accumulator / inArray.length;

} // End arrayAverage().

3.3.2 构建jscript.browser包

如何获取正在使用应用程序的浏览器的标识信息?

/**
 * This function returns a string containing identification information
 * about the client
 *
 * @return String of browser identification information.
 */
jscript.browser.getBrowserIdentity = function() {

  return navigator.appName + " " + navigator.appVersion;

} // End getBrowserIdentity().

这个代码会返回字符串,它由浏览器的名称和版本组成,比如:
Microsoft Internet Explorer 4.0 ( compatible;MSIE 6.0;Windows NT 5.1; SV1; Maxthon;
WebCloner; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)
Microsoft Internet Explorer 部分是navigator.appName( )的结果,剩下的是navigator.appVersion()的结果。

3.3.3 构建jscript.datetime包

1. 怎样知道一个给定月有多少天?

/**
 * This function will return the number of days in a given month and year,
 * taking leap years into account.
 *
 * @param  inMonth The month, where January = 1 and December = 12.
 * @param  inYear  The year to check the month in.
 * @return         The number of days in the specified month and year.
 */
jscript.datetime.getNumberDaysInMonth = function(inMonth, inYear) {

  inMonth = inMonth - 1;
  var leap_year = this.isLeapYear(inYear);
  if (leap_year) {
    leap_year = 1;
  } else {
    leap_year = 0;
  }
  if (inMonth == 3 || inMonth == 5 || inMonth == 8 || inMonth == 10) {
    return 30;
  } else if (inMonth == 1) {
    return 28 + leap_year;
  } else {
    return 31;
  }

} // End getNumberDaysInMonth().

2.怎样判断给定的年份是否为闰年

/**
 * This function will determine if a given year is a leap year.
 *
 * @param  inYear The year to check.
 * @return        True if inYear is a leap year, false if not.
 */
jscript.datetime.isLeapYear = function(inYear) {

  if ((inYear % 4 == 0 && !(inYear % 100 == 0)) || inYear % 400 == 0) {
    return true;
  } else {
    return false;
  }

} // End isLeapYear().

3.3.4 构建jscript.debug包

1.如何显示任意的一个对象的所有属性及它们的值呢?

/**
 * This simple function is one of the handiest: pass it an object, and it
 * will pop an alert() listing all the properties of the object and their
 * values.
 *
 * @param inObj The object to display properties of.
 */
jscript.debug.enumProps = function(inObj) {

  var props = "";
  var i;
  for (i in inObj) {
    props += i + " = " + inObj[i] + "\n";
  }
  alert(props);

} // End enumProps().

对每一个属性,我们把它的名字(i的值)和值(使用数组表示法来获取成员)添加到一个字符串中。最后,将字符串传给alert( ),就达到目标了。

2.如何实现一个健壮的自动记录日志机制呢,类似于Jakarta Commons Logging?

可以基于严重级别来记录(或者不记录)日志的日志系统

/**
 * This is a very simple logger that sends all log messages to a specified
 * DIV.
 */
jscript.debug.DivLogger = function() {


  /**
   * The following are faux constants that define the various levels a log
   * instance can be set to output.
   */
  this.LEVEL_TRACE = 1;
  this.LEVEL_DEBUG = 2;
  this.LEVEL_INFO  = 3;
  this.LEVEL_WARN  = 4;
  this.LEVEL_ERROR = 5;
  this.LEVEL_FATAL = 6;


  /**
   * These are the font colors for each logging level.
   */
  this.LEVEL_TRACE_COLOR = "a0a000";
  this.LEVEL_DEBUG_COLOR = "64c864";
  this.LEVEL_INFO_COLOR  = "000000";
  this.LEVEL_WARN_COLOR  = "0000ff";
  this.LEVEL_ERROR_COLOR = "ff8c00";
  this.LEVEL_FATAL_COLOR = "ff0000";


  /**
   * logLevel determines the minimum message level the instance will show.
   */
  this.logLevel = 3;


  /**
   * targetDIV is the DIV object to output to.
   */
  this.targetDiv = null;


  /**
   * This function is used to set the minimum level a log instance will show.
   *
   * @param inLevel One of the level constants.  Any message at this level
   *                or a higher level will be displayed, others will not.
   */
  this.setLevel = function(inLevel) {

    this.logLevel = inLevel;

  } // End setLevel().


  /**
   * This function is used to set the target DIV that all messages are
   * written to.  Note that when you call this, the DIV's existing contents
   * are cleared out.
   *
   * @param inTargetDiv The DIV object that all messages are written to.
   */
  this.setTargetDiv = function(inTargetDiv) {

    this.targetDiv = inTargetDiv;
    this.targetDiv.innerHTML = "";

  } // End setTargetDiv().


  /**
   * This function is called to determine if a particular message meets or
   * exceeds the current level of the log instance and should therefore be
   * logged.
   *
   * @param inLevel The level of the message being checked.
   */
  this.shouldBeLogged = function(inLevel) {

    if (inLevel >= this.logLevel) {
      return true;
    } else {
      return false;
    }

  } // End shouldBeLogged().


  /**
   * This function logs messages at TRACE level.
   *
   * @param inMessage The message to log.
   */
  this.trace = function(inMessage) {

    if (this.shouldBeLogged(this.LEVEL_TRACE) && this.targetDiv) {
      this.targetDiv.innerHTML +=
      "
" + "[TRACE] " + inMessage + "
"
; } } // End trace(). /** * This function logs messages at DEBUG level. * * @param inMessage The message to log. */ this.debug = function(inMessage) { if (this.shouldBeLogged(this.LEVEL_DEBUG) && this.targetDiv) { this.targetDiv.innerHTML += "
" + "[DEBUG] " + inMessage + "
"
; } } // End debug(). /** * This function logs messages at INFO level. * * @param inMessage The message to log. */ this.info = function(inMessage) { if (this.shouldBeLogged(this.LEVEL_INFO) && this.targetDiv) { this.targetDiv.innerHTML += "
" + "[INFO] " + inMessage + "
"
; } } // End info(). /** * This function logs messages at WARN level. * * @param inMessage The message to log. */ this.warn = function(inMessage) { if (this.shouldBeLogged(this.LEVEL_WARN) && this.targetDiv) { this.targetDiv.innerHTML += "
" + "[WARN] " + inMessage + "
"
; } } // End warn(). /** * This function logs messages at ERROR level. * * @param inMessage The message to log. */ this.error = function(inMessage) { if (this.shouldBeLogged(this.LEVEL_ERROR) && this.targetDiv) { this.targetDiv.innerHTML += "
" + "[ERROR] " + inMessage + "
"
; } } // End error(). /** * This function logs messages at FATAL level. * * @param inMessage The message to log. */ this.fatal = function(inMessage) { if (this.shouldBeLogged(this.LEVEL_FATAL) && this.targetDiv) { this.targetDiv.innerHTML += "
" + "[FATAL] " + inMessage + "
"
; } } // End fatal(). } // End DivLogger().

注意在trace( )函数之后,实际上还应该有更多的函数:debug( ), info( ), warn( ), error( ), 和fatal( ), 分别对应每一个日志级别。我省略它们只是为了节约些空间,但它们本质上是trace( )方法,替换掉trace这个名字。
为了达到这个效果,你需要实例化一个DivLogger,如下:

var log = new jscript.debug.DivLogger( );

这个日志记录程序还有另外一个事情要做:调用setTargerDiv( ), 给它传递一个< div >元素的引用,所有日志输出信息都应该写到这里。
然后,调用log.xxxx(yyyy),xxxx指严重级别(trace, debug, info, warn, error或fatal ), yyyy指日志信息。也可以调用log.setLevel( )来设置需要记录的信息的级别。例如:

log.setLevel(log.LEVEL_ERROR);

之后,只有LEVEL_ERROR或LEVEL_FATAL级别的信息才记入日志。

3.3.5 构建jscript.dom包

1.如何将任意一个DOM元素居中

/**
 * Center a given layer on the screen horizontally.
 *
 * @param inObj A reference to the element (presumably a layer) to center.
 */
jscript.dom.layerCenterH = function(inObj) {

  var lca;
  var lcb;
  var lcx;
  var iebody;
  var dsocleft;
  if (window.innerWidth) {
    lca = window.innerWidth;//内容填充的实际大小
  } else {
    lca = document.body.clientWidth;//内容填充的实际大小
  }
  lcb = inObj.offsetWidth;
  lcx = (Math.round(lca / 2)) - (Math.round(lcb / 2));
  iebody = (document.compatMode &&
    document.compatMode != "BackCompat") ?//是否向后兼容
    document.documentElement : document.body;
  dsocleft = document.all ? iebody.scrollLeft : window.pageXOffset;//dobument.all是否在DOM中出现,出现则IE
  inObj.style.left = lcx + dsocleft + "px";

} // End layerCenterH().

2. 如何竖直居中?

/**
 * Center a given layer on the screen vertically.
 *
 * @param inObj A reference to the element (presumably a layer) to center.
 */
jscript.dom.layerCenterV = function(inObj) {

  var lca;
  var lcb;
  var lcy;
  var iebody;
  var dsoctop;
  if (window.innerHeight) {
    lca = window.innerHeight;
  } else {
    lca = document.body.clientHeight;
  }
  lcb = inObj.offsetHeight;
  lcy = (Math.round(lca / 2)) - (Math.round(lcb / 2));
  iebody = (document.compatMode &&
    document.compatMode != "BackCompat") ?
    document.documentElement : document.body;
  dsoctop = document.all ? iebody.scrollTop : window.pageYOffset;
  inObj.style.top = lcy + dsoctop + "px";

} // End layerCenterV().

3.当使用一个Ajax请求时,得到一堆返回的内容。如果那堆内容中包含一些< script >段,如何执行?

/**
 * This function is used to execute all the script blocks found in a
 * chunk of text.  This is typically used to execute the scripts found in
 * an AJAX response.
 *
 * @param inText The text to parse scripts from to execute.
 */
jscript.dom.execScripts = function (inText) {

  var si = 0;
  while (true) {
    // Finding opening script tag.
    var ss = inText.indexOf("<" + "script" + ">", si);
    if (ss == -1) {
      return;
    }
    // Find closing script tag.
    var se = inText.indexOf("<" + "/" + "script" + ">", ss);
    if (se == -1) {
      return;
    }
    // Jump ahead 9 characters, after the closing script tag.
    si = se + 9;
    // Get the content in between and execute it.
    var sc = inText.substring(ss + 8, se);
    eval(sc);
  }

} // End execScripts().

4. 如何引用任意数量的DOM?

document.getElementById( )来获得一个DOM元素的引用,获得一批元素的引用:

/**
 * This function accepts one or more DOM IDs and returns an array which
 * contains a reference to all of them.  If no arguments are passed in,
 * null is returned.  If a single ID is passed in, a single element is
 * returned.  If more than one ID is passed in, an array is passed back.
 *
 * @param  ?? A variable number of arguments, each being a DOM ID to get a
 *            reference to (or a single ID).
 * @return    Null is no arguments passed in, or a reference to a single
 *            DOM element if one ID passed in, or an array of references to
 *            DOM elements if multiple IDs passed in.
 */
jscript.dom.getDOMElements = function() {

  if (arguments.length == 0) {
    return null;
  }
  if (arguments.length == 1) {
    return document.getElementById(arguments[0]);
  }
  var elems = new Array();
  for (var i = 0; i < arguments.length; i++) {
    elems.push(document.getElementById(arguments[i]));
  }
  return elems;

} // End getDOMElements().

这个函数接受可变数量的参数,认为它们是DOM元素ID。每个JavaScript函数天生指向一个arguments数组, 也就是传入这个函数的所有参数的数组。
所以,如果没有传入任何参数,这个函数就返回空,它本身是一个非法调用。
传入一个参数, 执行典型的document.getElementById()并返回它。
传入参数不止一个, 循环arguments数组,对每个参数执行document.getElementById()。把调用产生的结果压入到新创建的一个数组, 并且当完成时返回那个数组。数组中每个元素,现在都是指向一个传入的DOM ID的引用。

3.3.6 构建jscript.form包

1. 如何从一个HTML表单生成XML?

/**
 * This function takes an HTML form and constructs an XML document from it,
 * using the specified root element.
 *
 * @param  inForm        A reference ot the HTML form object to serialize.
 * @param  inRootElement The root element the XML dccument should use.
 * @return               A string of XML constructed from serializing the
 *                       specified form.
 */
jscript.form.formToXML = function(inForm, inRootElement) {

  if (inForm == null) {//接收一个表单inForm的引用
    return null;
  }
  if (inRootElement == null) {//接收一个字符串inRootElement,XML文档根元素的名字
    return null;
  }
  var outXML = "<" + inRootElement + ">";//创建outXML字符串,向它添加根元素
  var i;
  for (i = 0; i < inForm.length; i++) {//遍历表单的子节点。取得每个节点的类型,名字,值。
    var ofe = inForm[i];
    var ofeType = ofe.type.toUpperCase();
    var ofeName = ofe.name;
    var ofeValue = ofe.value;
    if (ofeType == "TEXT" || ofeType == "HIDDEN" ||
      ofeType == "PASSWORD" || ofeType == "SELECT-ONE" ||//select-one在不是多选时,是你在< select>域中看到的值
      ofeType == "TEXTAREA") {//查看类型
      outXML += "<" + ofeName + ">" + ofeValue + " + ofeName + ">"//向XML字符串中添加一个元素
    }
    if (ofeType == "RADIO" && ofe.checked == true) {//对于radio域,检查每一个,即使它们全在同一组
      outXML += "<" + ofeName + ">" + ofeValue + " + ofeName + ">"
    }
    if (ofeType == "CHECKBOX") {//根据对应项是否被选中而发送值"true"或"false"。
      if (ofe.checked == true) {
        cbval = "true";
      } else {
        cbval = "false";
      }
      outXML = outXML + "<" + ofeName + ">" + cbval + " + ofeName + ">"

    }
    outXML += "";
  }
  outXML += " + inRootElement + ">";
  return outXML;

} // End formToXML().

2.如何在< select>域里查找并随意选择一个指定的选项?

找到它并不选择它。

/**
 * This function will determine is a select element contains a specified
 * option, and optionally will select it.
 *
 * @param  inSelect          A reference to the select object to search.
 * @param  inValue           The value to search for.
 * @param  inJustFind        True to just determine if the value exists, false
 *                           to also select it.
 * @param  inCaseInsensitive If true, the search will ignore case.  If false
 *                           only an exact case match will be found.
 * @return                   True if an option with the specified value is
 *                           found in the select, false if not.
 */
jscript.form.selectLocateOption = function(inSelect, inValue, inJustFind,
  inCaseInsensitive) {

  if (inSelect == null ||
    inValue == null || inValue == "" ||
    inCaseInsensitive == null ||
    inJustFind == null) {
    return;
  }
  if (inCaseInsensitive) {
    inValue = inValue.toLowerCase();
  }
  var found = false;
  var i;
  for (i = 0; (i < inSelect.length) && !found; i++) {
    var nextVal = inSelect.options[i].value;
    if (inCaseInsensitive) {
      nextVal = nextVal.toLowerCase();
    }
    if (nextVal == inValue) {
      found = true;
      if (!inJustFind) {
        inSelect.options[i].selected = true;
      }
    }
  }
  return found;

} // End selectLocateOption().

3.如何在一个< select>中提供全选功能?

/**
 * This function will select all the options in a specified select element.
 *
 * @param inSelect The select element to select all options in.
 */
jscript.form.selectSelectAll = function(inSelect) {

  if (inSelect == null || !inSelect.options || inSelect.options.length == 0) {
    return;
  }
  var i;
  for (i = 0; i < inSelect.options.length; i++) {
    inSelect.options[i].selected = true;
  }

} // End selectSelectAll().

取消选中
/**
 * This function will unselect all the options in a specified select element.
 *
 * @param inSelect The select element to unselect all options in.
 */
jscript.form.selectUnselectAll = function(inSelect) {

  if (inSelect == null || !inSelect.options || inSelect.options.length == 0) {
    return;
  }
  var i;
  for (i = 0; i < inSelect.options.length; i++) {
    inSelect.options[i].selected = false;
  }

} // End selectUnselectAll().

3.3.7 构建jscript.lang包

如何获得一个对象的属性并把它们复制给另一个对象?

/**
 * This function copies all properties from a source object to a destination
 * object, optionally overwriting matching existing members.
 *
 * @param  inSrcObj   The object to copy FROM.
 * @param  inDestObj  The object to copy TO.
 * @param  inOverride If true, any member in the destination object that
 *                    already exists will be overwritten.
 * @return            The destination object with members copied from the
 *                    source object,
 */
jscript.lang.copyProperties = function(inSrcObj, inDestObj, inOverride){

  var prop;
  for (prop in inSrcObj) {
    if (inOverride || !inDestObj[prop]) {
      inDestObj[prop] = inSrcObj[prop];
    }
  }
  return inDestObj;

} // End copyProperties().

3.3.8 构建jscript.math包

如何在一个指定范围内生成随机数?

/**
 * This function returns a random integer number within a specified range.
 * If the specified minumum is greated than the maximum, zero is returned.
 *
 * @param  inMin The minimum value of the range, inclusive.
 * @param  inMax The maximum value of the range, inclusive.
 * @return       A random number within the specified range.
 */
jscript.math.genRandomNumber = function(inMin, inMax) {

  if (inMin > inMax) {
    return 0;
  }
  return Math.round(inMin + (inMax - inMin) * Math.random());

} // End genRandomNumber().

3.3.9 构建jscript.page包

1.如何用程序启动对当前页面的打印?

window.print(),只能在最近的浏览器用。

/**
 * This function invokes the browser's print function, if the browser version
 * is high enough.
 */
jscript.page.printPage = function() {

  if (parseInt(navigator.appVersion) >= 4) {
    window.print()
  }

} // End printPage().

2.如何使用一个传入页面的参数呢?

/**
 * This function returns the value of a specified parameter that may have
 * been passed to this page, or it returns an array of all parameters passed
 * to the page, depending on the input parameter.
 *
 * @param  inParamName The name of the parameter to get values for, or null
 *                     to return all parameters.
 * @return             A string value, the value of the specified parameter,
 *                     or an associative array of all parameters if null
 *                     was passed in.
 */
jscript.page.getParameter = function(inParamName) {

  var retVal = null;
  var varvals = unescape(location.search.substring(1));//获取查询字符串的引用的方法。通过从URL的第2个字符开始,我们可以删除开头的问号,只留下参数。
  if (varvals) {
    var search_array = varvals.split("&");//把每个参数分隔开,得到一个数组。
    var temp_array = new Array();
    var j = 0;
    var i = 0;
    for (i = 0; i < search_array.length; i++) {//遍历数组,每个元素进一步用等号分割,因为每个参数都是一个name=value对
      temp_array = search_array[i].split("=");
      var pName = temp_array[0];
      var pVal = temp_array[1];
      if (inParamName == null) {
        if (retVal == null) {
          retVal = new Array();
        }
        retVal[j] = pName;
        retVal[j + 1] = pVal;
        j = j + 2;
      } else {
        if (pName == inParamName) {
          retVal = pVal;
          break;
        }
      }
    }
  }
  return retVal;

} // End getParameters().

所有参数都返回的话,一开始会初始化一个新的数组,向里面添加参数及其值,name,value,name,value等。在处理完参数后,返回这个数组。

3.如何使用JavaScript打破一个框架?

/**
 * Call this function to break out of frames.
 */
jscript.page.breakOutOfFrames = function() {

  if (self != top) {
    top.location = self.location;
  }

} // End breakOutOfFrames().

打破框架,只要确保浏览器中的文档也是在顶部的。如果它是一个框架,那就是父框架文档。如果这个文档不是顶部文档,那么我们就把当前文档设置为顶部文档,这通常引发任何的框架被新文档(服务器返回的新结果)重写。

3.3.10 构建jscript.storage包

1.如何创建一个cookie并把它保存在客户端呢?

/**
 * Sets a cookie.
 *
 * @param inName   The name of the cookie to set.
 * @param inValue  The value of the cookie.
 * @param inExpiry A Date object representing the expiration date of the
 *                 cookie.
 */
jscript.storage.setCookie = function(inName, inValue, inExpiry) {

  if (typeof inExpiry == "Date") {
    inExpiry = inExpiry.toGMTString();
  }
  document.cookie = inName + "=" + escape(inValue) + "; expires=" + inExpiry;

} // End setCookie().

每个cookie有名,值,过期时间。inName,inValue和inExpiry。时间需要GMT日期字符串形式,所以要允许inExpiry可以成为一个实际的Date对象,或者可能是一个GMT日期格式的字符串。
Date对象,调用toGMTString()方法获得适当的格式。然后, 设置document.cookie等于一个字符串,形式:xxxx=yyyy;expires=zzzz,其中xxxx是cookie的名字, yyyy是值,zzzz是日期字符串。
设置另一个cookie,第一个cookie不会被重写。???

2.如何获得一个指定cookie的值呢?

/**
 * Gets thbe value of a specified cookie.  Returns null if cookie isn't found.
 *
 * @param inName The name of the cookie to get the value of.
 */
jscript.storage.getCookie = function(inName) {

  var docCookies = document.cookie;
  var cIndex = docCookies.indexOf(inName + "=");
  if (cIndex == -1) {
    return null;
  }
  cIndex = docCookies.indexOf("=", cIndex) + 1;
  var endStr = docCookies.indexOf(";", cIndex);//每个cookie都有expires=zzzz字符串跟在后面,所以查找分号。
  if (endStr == -1) {
    endStr = docCookies.length;
  }
  return unescape(docCookies.substring(cIndex, endStr));

} // End getCookie().

3.如何删除cookie?

/**
 * Deletes a cookie.
 */
jscript.storage.deleteCookie = function(inName) {

  if (this.getCookie(inName)) {
    this.setCookie(inName, null, "Thu, 01-Jan-1970 00:00:01 GMT");
  }

} // End deleteCookie().

3.3.11 构建jscript.string包

1.如何计算一个子串在字符串中出现的次数?

/**
 * This function searches a string for another string and returns a count
 * of how many times the second string appears in the first.
 *
 * @param  inStr       The string to be searched.
 * @param  inSearchStr The string to search for.
 * @return             The number of times inSearchStr appears in inStr,
 *                     or 0 if inStr or inSearchStr is null or a blank string.
 */
jscript.string.substrCount = function(inStr, inSearchStr) {

  if (inStr == null || inStr == "" ||
    inSearchStr == null || inSearchStr == "") {
    return 0;
  }
  var splitChars = inStr.split(inSearchStr);
  return splitChars.length - 1;//XYZ中找Y,X Z,切成两段,一个Y,所以减一

} // End substrCount().

2.如何从字符串删除指定的字母?或从字符串中删除除了指定字母之外的其他任何字母?

/**
 * This function will take take an input string and either strip any
 * character that appears in a given list of characters, or will strip any
 * character that does NOT appear in a given list of characters.
 *
 * @param  inStr          The string to strip characters from.
 * @param  inStripOrAllow Either the value "strip" or "allow".
 * @param  inCharList     This is either (a) the list of characters that
 *                        will be stripped from inStr (when inStripOrAllow ==
 *                        "strip"), or (b) the list of characters that will
 *                        NOT be stripped from inStr (when inStripOrAllow ==
                          "allow".
 * @return                The value of inStr after characters have been
 *                        stripped as specified.
 */
jscript.string.stripChars = function(inStr, inStripOrAllow, inCharList) {

  if (inStr == null || inStr == "" ||
    inCharList == null || inCharList == "" ||
    inStripOrAllow == null || inStripOrAllow == "") {
     return "";
  }
  inStripOrAllow = inStripOrAllow.toLowerCase();
  var outStr = "";
  var i;
  var j;
  var nextChar;
  var keepChar;
  for (i = 0; i < inStr.length; i++) {
    nextChar = inStr.substr(i, 1);
    if (inStripOrAllow == "allow") {
      keepChar = false;
    } else {
      keepChar = true;
    }
    for (j = 0; j < inCharList.length; j++) {
      checkChar = inCharList.substr(j, 1);
      if (inStripOrAllow == "allow" && nextChar == checkChar) {
        keepChar = true;
      }
      if (inStripOrAllow == "strip" && nextChar == checkChar) {
        keepChar = false;
      }
    }
    if (keepChar == true) {
      outStr = outStr + nextChar;
    }
  }
  return outStr;

} // End stripChars().

3.如果不想改变字符串,只是测试一下是否只包含而合法字符或者只包含非法字符,怎么做?

/**
 * This function can check is a given string either only contains characters
 * from a list, or does not contain any characters from a given list.
 *
 * @param  inString    The string to validate.
 * @param  inCharList  A list of characters that is either (a) the only
 *                     characters allowed in inString (when inFromExcept
 *                     is == "from_list") or (b) the only characters that
 *                     cannot appear in inString (when inFromExcept is
 *                     == "not_from_list").
 * @param inFromExcept When this is "from_list", then inString may only
 *                     contain characters from inCharList.  When this is
 *                     "not_from_list", then inString can contain any character
 *                     except thos in inCharList.
 * @return             True if inString only contains valid characters,
 *                     as listed in inCharList when inFromExcept ==
 *                     "from_list", false if not, or true if inString does
 *                     not containt any of the characters listed in
 *                     inCharList when inFromExcept == "not_from_list".
 */
jscript.string.strContentValid = function(inString, inCharList, inFromExcept) {

  if (inString == null || inCharList == null || inFromExcept == null ||
    inString == "" || inCharList == "") {
    return false;
  }
  inFromExcept = inFromExcept.toLowerCase();
  var i;
  if (inFromExcept == "from_list") {
    for (i = 0; i < inString.length; i++) {
      if (inCharList.indexOf(inString.charAt(i)) == -1) {
        return false;
      }
    }
    return true;
  }
  if (inFromExcept == "not_from_list") {
    for (i = 0; i < inString.length; i++) {
      if (inCharList.indexOf(inString.charAt(i)) != -1) {
        return false;
      }
    }
    return true;
  }

} // End strContentValid().

4.如何在一个字符串中替换出现的所有某个子串?

/**
 * This function replaces a given substring of a string (all occurances of
 * it to be more precise) with a specified new substring.  The substrings
 * can of course be single characters.
 *
 * @param  inSrc The string to replace substring(s) in.
 * @param  inOld The substring to replace.
 * @param  inNew The new substring to insert.
 * @return       The value of inSrc with all occurances of inOld replaced
 *               with inNew.
 */
jscript.string.replace = function(inSrc, inOld, inNew) {

  if (inSrc == null || inSrc == "" || inOld == null || inOld == "" ||
    inNew == null || inNew == "") {
    return "";
  }
  while (inSrc.indexOf(inOld) > -1) {
    inSrc = inSrc.replace(inOld, inNew);
  }
  return inSrc;

} // End replace().

5.如何从字符串的开头删掉空格?(左侧,右侧,左右两侧)

/**
 * Function to trim whitespace from the beginning of a string.
 *
 * @param  inStr The string to trim.
 * @return       The trimmed string, or null if null or a blank string was
 *               passed in.
 */
jscript.string.leftTrim = function(inStr) {

  if (inStr == null || inStr == "") {
    return null;
  }
  var j;
  for (j = 0; inStr.charAt(j) == " "; j++) { }
  return inStr.substring(j, inStr.length);

} // End leftTrim().


/**
 * Function to trim whitespace from the end of a string.
 *
 * @param  inStr The string to trim.
 * @return       The trimmed string, or null if null or a blank string was
 *               passed in.
 */
jscript.string.rightTrim = function(inStr) {

  if (inStr == null || inStr == "") {
    return null;
  }
  var j;
  for (j = inStr.length - 1; inStr.charAt(j) == " "; j--) { }
  return inStr.substring(0, j + 1);

} // End rightTrim().


/**
 * Function to trim whitespace from both ends of a string.
 *
 * @param  inStr The string to trim.
 * @return       The trimmed string, or null if null or a blank string was
 *               passed in.
 */
jscript.string.fullTrim = function(inStr) {

  if (inStr == null || inStr == "") {
    return "";
  }
  inStr = this.leftTrim(inStr);
  inStr = this.rightTrim(inStr);
  return inStr;

} // End fullTrim().

6.怎样把一个字符串分割成几个指定长度的片段?

/**
 * Breaks a string of text into chunks of a specified size.  It will break
 * on whitespace only, no mid-word breaks.
 *
 * @param  inText The text to break up.
 * @oaram  inSize The size of each chunk.
 * @return        An array containing X number of chunks.
 */
jscript.string.breakLine = function(inText, inSize) {

  if (inText == null || inText == "" || inSize <= 0) {//有一个需要切断的字符串,并且还要确认指定的大小大于等于1。
    return inText;
  }
  if (inText.length <= inSize) {//检查inText的大小
    return inText;
  }
  var outArray = new Array();
  var str = inText;
  while (str.length > inSize) {
    var x = str.substring(0, inSize);
    var y = x.lastIndexOf(" ");
    var z = x.lastIndexOf("\n");
    if (z != -1) {
      y = z;
    }
    if (y == -1) {
      y = inSize;
    }
    outArray.push(str.substring(0, y));
    str = str.substring(y);
  }
  outArray.push(str);
  return outArray;

} // End breakLine().

小结

本章:如何创建基本的包结构,帮助避免命名空间的冲突,避免过多使用全局变量以及避免到处都是函数。

你可能感兴趣的:(JavaScript实战,Frank,W.,Zammetti)