NetSpace公司在最初将其脚本语言命名为LiveScript ,后来NetSpace在与Sun 合作之后为了推广该语言,由于当时Java已经是十分流行的语言,并且是Sun公司开发的,因此NetSpace将其改名为JavaScript。
Script:脚本,手迹; 书写体铅字; 剧本、广播稿或者电影剧本;
JavaScript是一种脚本语言,Js的解释器就是JavaScript引擎,为浏览器的一部分。
JavaScript最初是由于以前网速很慢,所以NetSpace公司开发一种运行于浏览器中的语言,来进行一些表单验证判断,而现在Js几乎无所不能,如:
js有以下三部分组成:
ECMA:欧洲计算机制造联合会
1995年Netscape发布的JavaScript大获成功,恰巧这时微软进军浏览器市场,IE 3.0搭载了一个JavaScript的克隆版-JScript, 再加上ScriptEase,导致了三种不同版本的客户端脚本语言同时存在。为了建立语言的标准化,1997年,在Netscape、Sun、微软、Borland等公司的参与下制订了ECMAScript
从此以后的Javascript,JScript,ActionScript等脚本语言都是基于ECMAScript标准实现的。
所以,ECMAScript实际上是一种语言在语法和语义上的标准。在JavaScript,JScript和ActionScript中声明变量,操作数组等语法完全一样。但是在操作浏览器对象等方面又有各自独特的方法,这些都是各自语言的扩展。
一套操作浏览器功能的API
如通过BOM能操作浏览器窗口,弹出框,跳转,获得浏览器的分辨率等。。
一套操作页面元素的API
DOM可以把HTML看成文档树,可以通过DOM提供的API来操作树上的节点
js写在哪里,在CSS中,讲过三种类型,js和css是一一对应的。
使用script的src属性,连接到外部的.js文件,src属性起到一个占位的作用
js代码则写在js文件中。
1.建议使用第三种,外联样式,有助于结构分离
2.理论上来说<script>
标签放在html文档的任何位置都可以,规范起见,推荐放到body结束标签的末尾,包含到body标签内,如:
1 2 3 4 |
|
这样处理的好处是无需担心因页面未完成加载,造成DOM节点获取不到,使脚本报错的问题,而且能避免因脚本运行缓慢造成页面卡死的问题。
1.js中变量区分大小写
2.由于js是弱类型语言,所以没有int,string这种类型,定义变量一般使用var
var x; //声明变量
var y=10;//声明并赋值
var s1,s2,s3; //同时声明多个变量
var s1=1, s2=2 ,s3=3; //同时声明多个变量并赋值
3. 变量的命名遵循驼峰命名法(首字母小写,后面的大写):如userName,userPassword
js中的基本类型有:Number,String,Boolean,Undefined , Null
整数:
var num=10; //十进制整数
定义十六进制: 用0x前缀
int num =0xAB;
定义八进制: 用0前缀
int num =017;
浮点数:
var result=0.1+0.2 ; 结果不是0.3
js中不要判断两个浮点数是否相等
如下图:
如下图:
数值判断:
判断一个变量是否为Number类型可以使用IsNaN
IsNaN: is not a number
var str = 'a' ;
var str1= "b" ;
var str='aaaaaa';
console.log(str.length);
js中拼接字符串使用 +
console.log('hello'+'world');
undefined 表示一个声明了没有赋值的变量,变量只声明的时候默认是undefined
null 表示空,变量的值若想为null, 必须手动设置
如何定义:
//定义一个undefinity,只需声明就行
var a;
console.log(a);
//定义一个null,需要手动设置
var b=null;
console.log(b);
打印结果如下:
Object
类型判断的方法有很多:typeof, instanceof, constructor, prototype
typeof 的使用如下:
console.log(typeof 1 === 'number') // => true
console.log(typeof 'wjh' === 'string') // => true
console.log(typeof false === 'boolean') // => true
console.log(typeof [] === 'object') // => true
console.log(typeof {} === 'object') // => true
console.log(typeof null === 'object') // => true
console.log(typeof un === 'undefined') // => true
typeof 返回的结果是string类型的
typeof实际上是一个元运算符,所以不需要在typeof后面加上( ),但是加上也不会报错,也可以运行
1.转换成String类型
有两种方法toString() 和String()
//toString()
var age=18;
console.log(age.toString());
var b= true;
console.log(b.toString());
//String()
var age=18;
console.log(String(age));
var b= true;
console.log(String(b));
注意:toString方法不可以判断undefinity和null,会报错,但是可以使用String() 来判断。
2.转化成数值类型
var str='abc';
console.log(Number(str)); // => NaN
var b=true;
console.log(Number(b); // => 1
var s='123';
console.log(Number(s)); // => 123
var s1='123abv';
console.log(Number(s1)); // => NaN
parseInt(1) ; // => 1
parseInt('abc') ; // => NaN
parseInt(true) ; // => NaN
parseInt("123abc") // =>123
parseInt方法无法将boolean类型转化成int
parseInt方法在遇到第一个非数字时,就停止运算,直接返回前面的值,如上例第四句
跟parseInt十分相似,不同点在于:
parseFloat会解析第一个 . 遇到第二个 . 或者非数字则结束解析,直接返回
若解析内容为整数时,则解析成整数
这种方式是通过在执行+ - 时,自动将其他类型的值,转化成数值类型
如:
var str='123';
console.log(+str); // => 123
var str='456';
console.log(-str); // => -456
var str='123abc';
console.log(+str); // => NaN
var isOK=true;
console.log(+isOk); // => 1
若有非数字,则转换失败,输出NaN
和上面的取正负类似,也是在执行运算的时候,将其他类型转换成数值类型,在做算术运算。
3.转换成布尔类型Boolean
使用Boolean() 方法 来转换成布尔类型
var str = 'abc';
var num = 123;
var a =null;
var b ; //b为undefined
console.log(Boolean(str)); // true
console.log(Boolean(num)); // true
console.log(Boolean(a)); // false
console.log(Boolean(b)); // false
只有五种情况Boolean()方法 会将其他类型会返回false:
null undefined ' ' 空字符串 0 NaN
+ - * / % 这些都是运算符
++a和a++ 都是表达式,都会返回一个值。
区别就是从左往右看,++a 是 把a+1 再返回 ; 而 a++ 则是先返回a ,再对a+1.
如:
var a=0;
console.log(a++); // 0
console.log(a); // 1
var b=0;
console.log(++b); // 1
console.log(b); // 1
简单来说: == 代表相同, ===代表严格相同
当进行双等号比较时候: 先检查两个操作数数据类型,如果相同, 则进行三等比较, 如果不同, 则愿意为你进行一次类型转换, 转换成相同类型后再进行比较
而三等比较时, 如果类型不同,直接就是false.
双等号==:
(1)如果两个值类型相同,再进行三个等号(===)的比较
(2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:
1)如果一个是null,一个是undefined,那么相等
2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较
三等号===:
(1)如果类型不同,就一定不相等
(2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN( ) 来判断)
(3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。
(4)如果两个值都是true,或是false,那么相等
(5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等
(6)如果两个值都是null,或是undefined,那么相等
定义数使用中括号 [ ] :
var nums=[]; //定义空数组
var names=[1,2,3,5,6];
console.log(names[3]); // 5
数组内的类型可以不一致:
var names=[ 1 , 'abc' , 1.2 , true]; //正确,但是不推荐这样使用
数组的长度用length 来获取
var names=[1,2,3,6];
console.log(names.length); // 5
修改数组中的值,可以直接赋值:
var names=[1,2,3,6];
names[0] = 100;
数组的长度可以动态改变,如:
var names=[1,2,3,4];
names[100] = 100;
console.log(names);
输出如下:
建议写完一句代码后加分号,有些浏览器不加分号也不会报错,但为了代码稳定(解析出错)还是建议使用分号断句。
function functionName(parameters1,parameters2) {
执行的代码
}
与C++,java不一样的是,js的函数没有public/private的修饰,也没有void/int的返回值修饰,也没有形参的void getMax(int x,int y) { } 这样的形参列表,而是直接写, 如 function getMax( x , y ) { }
//java的写法
prublic void getMax(int x,int y) {
.....
}
//js的写法
function getMax( x , y ) {
.....
}
分号是用来分隔可执行JavaScript语句。
由于函数声明不是一个可执行语句,所以不以分号结束。
function sum()
{
console.log(arguments[0],arguments[1]);
}
sum(2,4);
输出2,4
在任何函数内部都可以使用arguments这个对象,来取出实际传进来的参数
arguments非常想数组,但是不是数组
当参数固定时,建议使用形参表,当参数的个数不确定时,再使用arguments.
JavaScript 函数可以通过一个表达式定义。
函数表达式可以存储在变量中,如:
var x = function (a, b) { return a * b };
在函数表达式存储在变量x中后,变量也可作为一个函数使用,如:
var x = function (a, b) {return a * b};
var z = x(4, 3);
以上函数实际上是一个 匿名函数 。匿名函数和普通函数的区别就是少一个函数名称。
var x =function (parameters1,parameters2) {
执行的代码
}
函数存储在变量中,不需要函数名称,通常通过变量名来调用。而且匿名函数不能单独写,必须要有一个变量来接。否则报错
正常的函数也能被储存在一个变量中:
var x = function sum(a, b) { return a + b };
但是呢,这样写没有实际的意义,因为已经可以函数已经有一个名字sum了,所以没有必要再加一个x变量来表示
通过上面第三点,我们知道一个函数可以被赋值到一个变量,然后通过该变量来实现调用,
那么如果不用一个变量来接这个函数的话,有什么方法能调用呢?
答案是可以使用自调用函数,如:
(function (){
console.log('我是自调用函数');
})();
上面的代码等价于:
var x=function (){
console.log('我是自调用函数');
};
x();
就是把一个函数用括号包起来,就相当于一个匿名变量了,然后再通过括号来调用该变量,也就是调用该函数。
函数的类型为function,可以通过typeof 来输出函数的类型:
var fuc= function sum();
console.log(typeof fuc);
输出的值就是 function
函数作为参数,如:
var fn =function() { console.log('我是一个传进来的函数');};
function test(fn){
fn();
}
test(fn);
函数作为返回值,如:
var fn=function(){
console.log('我是一个被返回的函数');
};
function test(fn){
return fn;
}
var x=test(fn);
x();
全局作用域:
在script标签中或者在一个独立的js文件中定义的变量 就是全局变量,在任何位置都能访问。
局部作用域:
在任何函数的内部都有一个局部作用域,在函数内定义的变量,只有在函数内部才能访问。
在js中,局部作用域 就等于 函数作用域
我们知道在一般的编程语言中,都是有块级作用域的,既在一对花括号内定义的变量,无法在花括号外面访问。
如java:
for(int i=0;i<10;i++)
{
int j=5;
}
System.out.println(j+"");
这是编译器会提示报错: j cannot be resolved to a variable
可见java是无法在块作用域外访问变量的。
但是js是可以的,如 :
function test(){
for (var i = 0; i < 100; i++) {
var j=i;
}
console.log(j);
}
test();
输出99.
可见,在块外,块中定义的变量i仍然是可以访问的。既在一个函数中的任何位置定义的变量在该函数中的任何地方都是可见的
也就是说,JS并不支持块级作用域,它只支持函数作用域,
那么我们该如何使JS拥有块级作用域呢?是否还记得,在一个函数中定义的变量,当这个函数调用完后,变量会被销毁,我们
否可以用这个特性来模拟出JS的块级作用域呢?看下面这个DEMO:
function test(){
(function(){
for (var i = 0; i < 100; i++) {
var j=i;
}}) ();
console.log(j);
}
test();
此时提示错误了:Uncaught ReferenceError: j is not defined
这正是在把一个代码断用() 包起来,成为另一个函数,然后实现自调用,自调用完毕后,会销毁该函数中的变量,因此实现了块作用域隔离
js只有两个作用域,就是全局作用域和函数作用域。
scpript标签开启了一个全局作用域,然后里面的函数1会开启一个函数作用域,这个函数1下面如果还定义函数2,那么会在
函数2中继续开启一个作用域,这样就形成了一个作用域链。
js解释器在寻找变量名称会在当前作用域找,然后一级级往上。如上就是先在函数2的作用域里找 j 变量,找不到在去函数1的作用域找,找不到再去全局作用域中找
跟C++的预编译一样,js在执行过程前,要进行预解析
预解析:
1.变量提升,把变量的声明(不包括赋值),把变量声明提升到当前作用域的最上面
2.函数提升,把函数的声明(不包括调用),把函数声明提升到当前作用域的最上面
之前我们分析了作用域,注意预解析是提升到当前作用域最上方
举例1:
console.log(num);
var num =10;
结果输出undefined.
按照上面的预解析流程:
1.首先找到所有的变量和函数的声明
2.找到了var num=10;
3.注意var num=10;这句话其实分为两部分,是声明+赋值,分别是var num;和 num =10;
4.然后把var num;这个声明提升到最上面,就只剩下了num=10;
5.然后其他代码原封不动,就变成下面这样了:
预解析后实际代码为:
var num;
console.log(num);
num= 10;
举例2:
f1();
function f1(){
console.log('hello');
}
输出hello
跟上面同理:
预解析后实际代码为:
function f1(){
console.log('hello');
}
f1();
举例三:
var a =25;
function abc(){
alert(a);
var a=10;
}
abc();
预解析过程:
1.找到所有变量的声明和函数的声明
2.找到了var a ; 提升到最上方,剩下a=25;不动
3.找到了function abc()的声明,然后把函数声明放到最上面就变成了这样:
var a ;
function abc(){
alert(a);
var a=10;
}
a=25;
abc();
4.继续,在abc函数中也要进行预解析,发现了var a=10;然后把var a; 提升到当前函数的最上方
5.最后预解析的结果为:
var a ;
function abc(){
var a;
alert(a);
a=10;
}
a=25;
abc();
所以按照js从上往下执行,会输出undefined
之前的理解,对象就是Object,其他的对象都会继承Object类型,而Object类型通常会有toString ..等内置的方法。
对象是指包含一系列属性和方法的特殊的数据.
Object是一个对象,而且JavaScript 中的所有事物都是对象:字符串、数值、数组、函数... (除了null和undefined) ,他们都继承自Object
JavaScript 中有六种数据类型,包括五种基本数据类型(Number,String,Boolean,Undefined,Null),和复杂数据类型Object
那这不是冲突了吗,Number,String不是基本数据类型吗,他们和复杂数据类型Object不一样,那为什么又说他们也是对象呢,确实不一样,但是我们在使用的时候,js解释器会帮我们把Number,String,Boolean包装成对象,所以就有了万物皆对象,如果没有包装的Number,String,Boolean 并不是对象,只有包装后的才是对象。
创建对象的几种方式:
var dog={
name:'jack',
type:'哈士奇',
age:'5',
color:'black',
eat:function(){
console.log(this.name+'啃骨头');
}
}
console.log(dog.name);
console.log(dog.age);
dog.eat();
js中对象用{ } 花括号来定义,在{ }中以键值对的形式,可以定义属性和方法
使用 对象名.属性名 的方式来访问属性,如 dog.name
还可以使用对象名[ ' 属性名 '] 的方式来访问属性,如 dog[ 'type' ]
数组是用 数组名[ 索引值],如array[0] 来访问第n个元素,而对象则是用 对象名[' 属性名'] 来访问属性
使用 对象名.方法名() 的方式调用方法,如dog.eat
在对象中,定义方法的写法为 方法名: function (paramas ...) { }
而一般的函数写法为: function 方法名 (params ...) { }
要注意区别
创建一个空对象
var a={ } :
person=new Object();
person.firstname="John";
person.lastname="Doe";
person.age=50;
person.eyecolor="blue";
js中对象可以动态的添加属性和方法,如person.child='小明' ;这样就为person添加了一个属性。
function Person(name,age){
this.name=name;
this.age=age;
}
var ps=new Person('zs',24);
使用自定义函数来创建方法的要素有两点,第一必须有一个非匿名的函数,第二是使用new 关键字来创建。
js创建对象和c#的区别在于:
第一种方法,C#中不存在直接使用字面量创建对象的方式
第二种方法:C#中 var obj=new Object();也可以创建对象, 但是这个对象仅仅是object,虽然是其他对象的基类,但是不等于其他对象,而js中则可以动态的为该对象添加对象
第三种方法:C#中是使用class来定义一个对象A,然后在class中预先定义好属性和方法,然后使用A a=new A();来创建A对象.。 这种方法和第三种很像,只是形式不同,但是都是使用构造函数来创建.
js是使用function来代表普通函数,又可以代表构造函数,然后使用new 关键字来代表创建一个对象,而C#中则是使用class里面定义好的构造函数来构造.
var a=new Object();和var a={}有什么区别吗?
没有区别,两者都是生成一个默认的Object对象。
js和其它语言一样,一切对象的基类都是Object,所以,new Object()和简易的 { } 是同样的空对象,就是默认的对象
本来我以为{}应该是一个没有任何属性和方法的对象,但事实证明,var a = { };a.toString() 等Object对象所具有的方法,a都具有。
由此也可以判断,其实a = { }就是a = new Objcet()的简单实现。
var obj={
name:'zs',
age:18,
func :function (){
console.log(this);
}
};
for(var key in obj)
{
//key就是对象的成员的名字,为字符串形式
//使用对象名['成员名'] 来访问对象的成员
console.log(key +'---'+ obj[key] );
}
结果为:
var obj={
name:'zs',
age:18,
func :function (){
console.log(this);
}
};
console.log(obj.name);
console.log(obj.func);
delete obj.name;
delete obj.func;
console.log(obj.name);
console.log(obj.func);
输出结果为:
this代表的就是本身,但是在js中this在不同的地方有不同的含义
一般的函数就是全局函数,那么this在全局函数中代表的是window,既当前窗体,如:
function func(){
console.log(this);
}
func();
打印结果为:
方法就是对象的成员函数,跟函数没什么区别,只是这个函数在对象中,所以称之为方法
在方法中,this指向的是该方法所属于的对象,如:
var obj={
name:'zs',
func :function (){
console.log(this);
}
};
obj.func();
构造函数的写法和普通函数没有任何区别,只是约定构造函数的第一个字母大写
所以调用构造函数,若使用new来调用构造函数,则this指向的是构造的对象,若是使用普通的() 来调用的话,就是普通函数,既全局函数,那么this就是window,既第一种情况,如:
function Person()
{
console.log(this);
}
//用new关键字调用构造函数
var zs=new Person();
//使用()调用,则Person为普通函数,既全局函数
Person();
打印结果为:
打印了两个结果,第一个为Per'son,既要构造的对象,第二个为window