JavaScript有个叫“变量提升”的特性,意为:
在函数里声明的所有变量会被提升到函数顶部声明(但不涉及到赋值)。
示例:
var a=0;
!function(){
alert(a);
var a=1;
}()
在函数外声明了变量a=0,之后在函数里重新声明了a=1。
在这中间我们弹出a,它的值不是0,而是undefined。这就是变量提升导致的。发生变量提升之后,函数里声明的a被提升到函数顶部声明了(但这并不涉及到赋值),所以代码实际上相当于这样:
var a=0;
!function(){
var a;
alert(a);
a=1;
}()
所以如果函数外已经声明了一个变量,那么就不要在函数内重复声明它,这样将会触发变量提前,可能会造成一些问题。
如果需要在函数内重复声明,那么将这些变量在函数顶部先声明但不赋值(就是写得和变量提升后的实际代码一样),可以让代码更直观。
其实这个概念是我昨天发布了搜索bilibili评论工具时,8q给我指出的。今天看书很巧的也看到了这个地方,弄清楚了。
window.onload = function() {
try {
if (test & amp; & amp; typeof(test) == "function") {
test();
} else {
alert("不存在的函数");
}
} catch(e) {}
}
function test() {
alert("函数执行……");
}
今天写了看图模式的js,然后执行的时候遇到了问题:函数必须在window.onload里面执行,window.onload在每个页面底部都有,但是看图模式的功能只需要用在文章页中,在其他页面里,因为找不到这个函数就会报错。所以找到了使用try catch语句判断函数是否存在的代码。
在js中,在函数内声明的变量是局部变量,所以函数内的变量不会污染到全局命名空间。下面的例子就是使用一个匿名函数来作为临时的命名空间:
<script type="text/javascript">
var a='saber';
(function () {//定义一个匿名函数
var a=16;alert(a);//代码块
}())//立即执行这个函数
alert(a);
</script>
这两个名为a的变量是互不影响的。
注意:在函数内定义的变量必须加上var来定义,否则,这个变量将是一个全局变量!
最外层的括号是为了让javascript解释器认出这是一个函数表达式,函数之后的空括号是立即执行这个函数。
查看详解
我们要创建两个“人”的对象,并且设置每个人的属性。
<table border="1">
<tr>
<td>名字</td>
<td>性别</td>
<td>年龄</td>
<td>喜欢</td>
<td>身高</td>
</tr>
<script type="text/javascript">
function creatMan (名字,性别,年龄,喜欢) {
this.名字=名字;
this.性别=性别;
this.年龄=年龄;
this.喜欢=喜欢;
}
var Saber=new creatMan('Saber','女',154,'士狼');
var Illya=new creatMan('Illya','女',150,'士狼');
creatMan.prototype.height = function (height) {
this.height=height+'cm';
}
Saber.height(154);
Illya.height(150);
document.write('<tr>')
for(attr in Saber){
document.write('<td>'+ Saber[attr] +'</td>')
}
document.write('</tr>')
document.write('<tr>')
for(attr in Illya){
document.write('<td>'+ Illya[attr] +'</td>')
}
document.write('</tr>')
</script>
</table>
输出如下:

这种创建对象的方式在w3c里称为“混合的构造函数/原型方式”,使用构造函数来完成对象的创建,并在函数中使用this来设置对象的属性,this指代当前对象。
身高这块是使用prototype追加了一个方法,在这个方法里设置了身高属性。一旦对构造函数使用prototype追加属性,则每个由该函数创建的对象也都有了该属性,即使未赋值。如果未赋值,则追加值为等号右边内容(如果右边是函数,即是函数的源代码)。
不需要对此构造函数产生的每个对象都追加属性时,用普通方法为单个对象赋值就可以了:
Saber.height='154cm';
查看w3c页面:ECMAScript 定义类或对象
我们都知道js中的函数可以传参,但有时候我们调用函数时,所需要传递的参数数量可能不确定。例如下例:
function checkType (value) {
for (var i = 0; i < arguments.length; i++) {
alert(arguments[i]);
};
}
checkType('10',10,false);
[/code]
我们要查看几个数值的类型,随时可能增删几个参数。问题来了,这些不定数量的实参在函数内怎么接收和处理呢?
在每个函数中,都有个名为 arguments 的变量,它以类似数组的形式保存了当前调用的参数。而它实际上并不是个数组,使用 typeof arguments 语句尝试会返回“object”(对象),所以它不能像 Array 一样使用 push 和 pop 等方法。即便如此,仍然可以使用下标以及长度属性(length)获取它的值。 所以对于不确定数量的实参,用arguments来使用再好不过了。
另可参考:ECMAScript arguments 对象
<div id="a" style="background:#DAE0F1;">
<p id="b">bbbbbbbbbbbbbbbbb</p>
</div>
<script type="text/javascript">
function createE (tagName,id,className,style,innerHTML,addway,parentId,reforeId) {
var newElement=document.createElement(tagName);
newElement.id=id;
newElement.className=className;
newElement.style.cssText=style;
newElement.innerHTML=innerHTML;
if (addway=='end') {
if (parentId=='body') {
document.body.appendChild(newElement);
}else{
document.getElementById(parentId).appendChild(newElement);
}
}
if(addway=='before'){
if (parentId=='body') {
document.body.insertBefore(newElement,document.getElementById(reforeId));
}else{
document.getElementById(parentId).insertBefore(newElement,document.getElementById(reforeId));
}
}
}
createE('div','aa','link','font-size: 30px;','追加在a的末尾','end','a','');
createE('h1','','','font-size: 30px;','插入在a中的b之前','before','a','b');
createE('h1','c','','font-size: 30px;','追加在body末尾','end','body','');
createE('h1','d','','font-size: 30px;','插入在body中的a之前','before','body','a');
</script>
输出如下:

今天写了个使用js创建页面元素的函数,如果有多个元素需要使用js来创建的话,倒还是可以方便一些的。函数参数如下:
元素的标签名,元素的id,元素的class名,元素的内部样式,元素的内部代码,追加方式(填写“end”或者“before”),追加到的父元素的id,父元素中子元素的id(仅当追加方式为before时填写)。
如果追加方式为end,则使用appendChild()方法追加到父元素内;如果追加方式为before,则使用insertBefore()方法插入到父元素内某个子元素之前。
考虑到body是创建元素时常用的一个节点,如果把父元素的id填写为“body”则会按body来处理。