变量和数据类型
关于对变量的说法,错误的是(B)
A. 一般使用var key=val的形式赋值
B. 由于javascript的动态特性,常常直接采取key= val的形式赋值
C. 若声明而未对变量赋值,该变量的值为undefined
D. var carname=”Volvo”;var carname;顺序执行后,caranme的值依然为Volvo
javascript 一般使用var key = val;的形式复制,声明变量的时候也要用var key; 如果不用var关键字,声明的就是全局变量,一般不要这么做;
变量重复声明不会错,js里有声明提前,如果两次声明都有赋值,如:var a=10; var a=100; 则变量a的值是100;
若var a=10; var a; 则变量a的值是10;第二次的var a;没什么用。
ECMAScript有5种简单的数据类型(基本数据类型)和一种复杂数据类–Object,Object本质上是由一组无序的名值对组成的。(基本类型可用typeof()函数来检测)
Undefined
未定义,声明变量是没有初始化,那么这个变量的值就是undefinedNull
空指针
alert(null == undefined) // true
当一个变量要刻意用来保存对象时,但还没有保存变量时,就该把变量的值设为nullBoolean
true/false,注意true不一定等于1, false也不一定等于0Number
String
使用 ” ” 或 ’ ‘
toString()方法 输出二进制,八进制,十进制等
var num = 10;
alert(num.toString()); // “10”
alert(num.toString(2)); // “1010”
alert(num.toString(8)); // “12”
alert(num.toString(10)); // “10”
alert(num.toString(16)); // “a”
String()方法 转化为string类型
var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
alert(String(value1)); // “10”
alert(String(value2)); // “true”
alert(String(value3)); // “null”
alert(String(value4)); // “undefined”
- Object
var o = new Object();
var o = new Object; // 不推荐
对于某个变量v,若其是值为 undefined , null, 0(数字0)
则if(v) 是 false
var a;
if(!a)
alert(1); // alert(1)
var b = 0;
if(b)
alert(2); // 不执行
var c = null;
if(c)
alert(3); // 不执行
运算问题
console.log(1+ "2"+"2");
console.log(1+ +"2"+"2");
console.log("A"- "B"+"2");
console.log("A"- "B"+2);
console.log(1+ “2”+”2”);
做加法时要注意双引号,当使用双引号时,JavaScript认为是字符串,字符串相加等于字符串合并。
因此,这里相当于字符串的合并,即为122.console.log(1+ +”2”+”2”);
第一个+”2”中的加号是一元加操作符,+”2”会变成数值2,因此1+ +”2”相当于1+2=3.
然后和后面的字符串“2”相合并,变成了字符串”32”.console.log(“A”- “B”+”2”);
“A”-“B”的运算中,需要先把”A”和”B”用Number函数转换为数值,其结果为NaN,在剪发操作中,如果有一个是NaN,则结果是NaN,因此”A”-“B”结果为NaN。
然后和”2”进行字符串合并,变成了NaN2.console.log(“A”- “B”+2);
根据上题所述,”A”-“B”结果为NaN,然后和数值2进行加法操作,在加法操作中,如果有一个操作数是NaN,则结果为NaN。
函数
函数参数
ECMAScript函数不介意传递进来多少个参数,也不在乎传进来的参数是什么类型
函数不需要指定返回值,因为函数可以在任何时候返回任何值
未指定函数返回值的,将会返回一个特殊的undefined值
没有函数签名概念,不能重载
参数传递按值传递
function doAdd(num){
num = num + 100;
return num;
}
var cnt = 1;
var rs = doAdd(cnt);
alert(cnt); // 1
alert(rs); // 101
可以传入参数 结合 arguments对象
如下的程序,可以正常运行打印结果
<script>
function sayHi(){
alert(arguments.length);
alert("hello"+arguments[0]+arguments[1])+arguments[2];
}
sayHi(1);
sayHi("a","b");
sayHi("A","B","C");
</script>
<script>
function doAdd(num1,num2){
alert(arguments[0]+num2);
alert(num1+arguments[1]);
alert(arguments[0]+arguments[1]);
}
doAdd(1,2);
</script>
<script>
alert(doAdd(10)); // 210 没有重载,第二次定义的函数有效
function doAdd(num){
return num+100;
}
function doAdd(num){
return num+200;
}
</script>
函数原型方法 bind apply call
参考http://developer.51cto.com/art/201503/466978.htm
代码1
var a = {
v : 0,
f : function(xx) {
this.v = xx;
}
}
alert(a.v); // 0
a.f(5);
alert(a.v); // 5
alert(this.v); // undefined
this对象指向了a本身,this绑定了对象a
代码2
function f(x){
this.v = x;
}
alert(this.v); // undefined
f(5);
alert(this.v); // 5
this绑定了全局的this
代码3 apply
function add(a,b)
{
this.c = a + b;
this.d = function()
{
alert("function d()");
}
}
// 函数给一个对象赋上属性
var obj = {};
add.apply(obj, [1,2]);
alert(obj.c); // 3
obj.d(); // function d()
alert(this.c); // undefined
add.apply(null,[3,4]); // null相当于全局赋上属性
alert(this.c); // 7
this.d(); // function d()
代码4
function a(xx, yy) {
this.x = xx;
y = yy;
alert(this);
alert(arguments);
}
a.call(null, 5, 55);
alert(this.x); // 5
alert(this.y); // 55
变量,作用域和内存问题
现有如下html结构
<ul>
<li>click me</li>
<li>click me</li>
<li>click me</li>
<li>click me</li>
</ul>
运行如下代码:
var elements=document.getElementsByTagName('li');
var length=elements.length;
for(var i=0;i<length;i++){
elements[i].onclick=function(){
alert(i);
}
}
```
依次点击4个li标签,哪一个选项是正确的运行结果()? 4,4,4,4
每个li标签的onclick事件执行时,本身onclick绑定的function的作用域中没有变量i,i为undefined,则解析引擎会寻找父级作用域,发现父级作用域中有i,且for循环绑定事件结束后,i已经赋值为4,所以每个li标签的onclick事件执行时,alert的都是父作用域中的i,也就是4。这是**作用域**的问题。
var a,b;
(function(){
alert(a); // undefined
alert(b); // undefined
var a=b=3; // a是局部变量, b是全局变量
alert(a); // 3
alert(b); // 3
})();
alert(a); // undefined
alert(b); // 3
“`
上述代码需要注意变量的作用域,注意 var a=b=3; // a是局部变量, b是全局变量
没有块级作用域
代码片段1
if(true){
var color = “blue”;
}
alert(color);代码片段2
for(var i = 0;i < 5; i++)
{
;
}
alert(i); //5
ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,引用类型值指那些可能由多个值构成的对象。引用类型的值是保存在类存中的对象,js不能直接操作内存,采用操作对象的引用。
不能给基本类型添加属性
var name = “123”;
name.age = 12;
alert(name.age); // undefined复制变量值,会分配不同的内存
var num1 = 5;
var num2 = num1;
引用类型
Object类型
创建Object的集中方式
new + 构造函数
var person = new Object() // var person new Object
person.name = “ac”;
person.age = 12;对象字面量表示法
var person = {
person.name : “ac”;
person.age : 12;
}var person ={}; // 写成var person; person将是undefined 不能加属性和方法
person.name = “ac”;
person.age = 12;
访问属性
person.name
person["name"]
Array类型
ECMAScript 数组大小动态调整,数组的每一项可以存储不同类型的值
创建数组
使用Array构造函数
var colors = new Array();
var colors = new Array(20); // 指定数组长度
var colors = new Array(“Blue”); //使用构造函数数组字面量表示法
var colors = [“red”,”green”, “blue”];
var names = [] ; // 空数组
var values = [1,2,] ; // 不要这样,会创建一个2项或3项的数组
var values = [,,,,,] ; // 不要这样,会创建一个5项或6项的数组
使用实例
var colors = ["red"];
colors[3] = "blue";
for(var i = 0 ;i < colors.length;i++) // 数组长度变成了4
{
alert(colors[i]); // red undefined undefined blue
}
toString() valueOf()
var colors = ["red"];
colors[3] = "blue";
alert(colors.toString());// red,,,blue
alert(colors.valueOf());
alert(colors);
colors.join(“|”); 用|作为每一项的分隔符
栈方法 push() pop()
var colors = ["red"];
colors.push("green");
colors.push("blue");
var item = colors.pop();
alert(item);
alert(colors.join("|"));
队列方法
排序方法
var values = [1,4,2,5,3];
values.reverse(); // 逆序
alert(values); // 3 5 2 4 1
function cmp(val1,val2)
{
if(val1 < val2){
return -1;
}else if(val1 > val2){
return 1;
}else{
return 0;
}
}
values.sort(cmp); // 按指定的排序函数排序
alert(values);
splice() 函数:删除,插入,替换
var values = [1,2,3,4,5];
var removedval = values.splice(1,2); //从第2项开始(0表示第1项) 删除2项
alert(removedval); // 2,3
alert(values); // 1,4,5
values.splice(1,0,10,11); //从位置1 开始插入 10,11
alert(values); // 1,10,11,4,5
var removedval = values.splice(1,2,2); //从位置1 开始删除两项,并添加2这一项
alert(removedval); // 10,11
alert(values); // 1,2,4,5
迭代方法 every() filter() forEach() map() some()
//every()相当于逻辑与
var arr = [1,2,3,4,5,6,7,8];
var everyRes = arr.every(function(item,index,array){
return (item>2);
});
alert(everyRes);
//some()相当于逻辑或
var someRes = arr.some(function(item,index,array){
return (item>2);
});
alert(someRes);
//filter()返回给定条件的数组
var filterRes = arr.filter(function(item,index,array){
return (item>2);
});
alert(filterRes);
//map()返回给定条件的数组
var mapRes = arr.map(function(item,index,array){
return (item*2);
});
alert(mapRes);
//forEach()没有返回值
arr.forEach(function(o,p,q){ //分别对应:数组元素,元素的索引,数组本身
alert(q[p]);
});
面向对象
对象的创建
创建对象,然后添加属性和方法
var person = new Object(); person.name = "abc", person.age = 10, person.job = "cs", person.sayName = function(){ alert(this.name); } alert(person.age); person.sayName();
字面量创建
var person ={ name: "abc", age: 10, job: "cs", sayName : function(){ alert(this.name); } } alert(person.age); person.sayName();
几种createObject的方法
http://www.cnblogs.com/mizzle/archive/2011/07/06/2099342.html
js对象继承
http://www.cnblogs.com/yangjinjin/archive/2013/02/01/2889563.html
闭包(closure)
作者: 阮一峰
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
this指针 ?
var name =" The Window ";
var object = {
name :" My object ",
getName: function (){
var name = " My Function ";
return this . name ;
}
}
alert(object.getName()); //My object
alert((object.getName)()); //My object
alert((object.getName = object.getName)()); //The Window
this是基于执行环境绑定:全局函数中,this指代window;函数作为对象方法调用时,this指代那个对象;
getName中的var name=”My Function”不能理解为给该函数添加属性name并且该属性的值为”My Function”!)
(object.getName = object.getName)这个函数表达式的意义是:
- 为 object 设置 getName 属性/方法。
- object.getName的值赋值给它
- 故该表达式的值就是函数本身:function(){var name = “My Funcition”;return this.name;}
等同于:
alert((function(){var name = ” My Function “; return this .name;})()); //The Window
全局函数,this为window,所以this.name为”The Window”!
匿名函数
var name =" The Window ";
var object = {
name :" My object ",
getName: function(){
return function(){
return this.name ;
};
}
}
alert(object.getName()()); //The Window
alert((object.getName = object.getName)()()); //The Window
题目:
<script>
var foo = "global foo";
var myObject = {
foo: "bar",
func: function(){
var self = this; // this 指向myObject对象
alert(this.foo); // bar
alert(self.foo); // bar
//()执行匿名函数
(function() {
alert(this.foo); // global foo,全局this(window的this) 调用全局this的foo变量或函数
alert(self.foo); // bar 匿名函数沿着上级找self,找到了myObject,得到myObject的foo变量
}());
}
};
myObject.func(); // 对象调用自己的方法
</script>