JavaScript是一种属于网络的脚本语言,常用来为网页添加各式各样的动态功能,是一种动态类型、弱类型、基于原型的语言。
它包括三个部分:ECMAScript、BOM和DOM。ECMAScript描述了该语言的语法和基本对象。BOM,浏览器对象模型,描述了与浏览器进行交互的方法和接口。DOM,文档对象模型,描述了处理网页内容的方法和接口。
js的使用:js代码写在script标签中,其引入方式和css样式的style标签一致。

一、变量、数据类型与运算符

  1.变量

  声明变量

- 通过var关键字声明一个或多个变量。
  - 声明变量的同时可以给其赋值(直接量,字面量),也可以不赋值,不赋值时默认值为undefined。
  - 变量命名遵循一般的命名规范:区分大小写,不能包含特殊字符,大小驼峰命名或下划线命名,不能以数字开头,命名含义明确等。
  - 变量在内存中会自动存储于释放。

  2.数据类型

js中的数据类型包括:字符串(String)、数字(Number)、布尔(Boolean)、数组(Array)、对象(Object)、空(Null)、未定义(Undefined)。

  隐式转换

// 转换为布尔类型
var a; // undefined.
var test = function(vec){
if(vec){
console.log("true");
}else{
console.log("false");
}
};
a = null;
a = 0; // 0值
a = NaN; // NaN值
a = ''; // 空字符串
test(a);
// 转换成数值型数据
var a;// undefined -> NaN
var b = 1;
a = null; // null -> 0
a = false; // false -> 0
a = "123"; // "12" -> 12
a = "123abc"; // "123abc" -> NaN
console.log(typeof a);
console.log(b + a);

  强制转换

// parseInt(string):将字符串类型转换成数值;
// parseFloat(string):将字符串类型转换成浮点型数值;
var a = "123";
console.log(typeof parseInt(a));
console.log(typeof parseFloat(a));
// String()和toString():将其它类型转换成字符串
var a = 123;
console.log(typeof String(a));
console.log(typeof a.toString());
// Boolean:将其它数据类型转换成布尔值。;
var a = undefined;
console.log(Boolean(a), typeof Boolean(a));

  3.运算符

  1.算术运算符

+、-、*、/、%、++、--
++、--分为前缀形式和后缀形式。前缀先自加(减)再执行运算,后缀先执行运算再自加(减)。

  2.赋值运算符和比较运算符

=、+=、-=、*=、/=、%=、.=
>、>=、<、<=、==、!=、===、!==

  3.逻辑运算符

&&、||、!

  4.三元运算符

// exp1?exp2:exp3
var a = 1231; // var a;
typeof a==="number"?console.log("true"):console.log("false");

  5.运算符优先级

运算符 描述
. [] () 字段访问、数组下标、函数调用以及表达式分组
++ -- - ~ ! delete new typeof void 一元运算符、返回数据类型、对象创建、未定义值
* / % 乘法、除法、取模
+ - + 加法、减法、字符串连接
<< >> >>> 移位
< <= > >= instanceof 小于、小于等于、大于、大于等于、instanceof
== != === !== 等于、不等于、严格相等、非严格相等
& 按位与
^ 按位异或
| 按位或
&& 逻辑与
|| 逻辑或
?: 条件
= oP= 赋值、运算赋值
, 多重求值

二、流程控制

  1.条件语句

// if(exp){执行代码段};
var a = 123; // var a;
if(typeof a === "number"){
console.log("true");
}
// if(exp){exp为true的代码段}else{exp为false的代码段};
var a = 123; // var a;
if(typeof a === "number"){
console.log("true");
}else {
console.log("false");
}
// if ... else if ...
var readline = require("readline");
var rl = readline.createInterface({
input: process.stdin,
out: process.stdout,
});
rl.question("请输入成绩: ", (number) => {
if(number > 100){
console.log("输入的成绩不能大于100!");
}else if(number > 80){
console.log("录入成功,A档");
}else if(number > 60){
console.log("录入成功,B档");
}else if(number > 0){
console.log("录入成功,C档");
}else{
console.log("输入的成绩不能小于0!")
}
rl.close();
});
rl.on("close", function () {
console.log("退出程序!");
process.exit();
});
var readline = require("readline");
var rl = readline.createInterface({
input: process.stdin,
out: process.stdout,
});
rl.question("请输入星期几: ", (day) => {
switch(day){
case "1":
console.log("今天吃炒面");
break;
case "2":
console.log("今天吃鱼香肉丝");
break;
case "3":
console.log("今天吃麻辣香锅盖饭");
break;
case "4":
console.log("今天吃豆丁胡萝卜");
break;
case "5":
console.log("今天公司聚餐");
break;
case "6":
console.log("今天吃泡面");
break;
case "7":
console.log("今天撸串");
break;
default:
console.log("input error.")
} rl.close();
});
rl.on("close", function () {
process.exit();
}
// switch ... case ...
var readline = require("readline");
var rl = readline.createInterface({
input: process.stdin,
out: process.stdout,
});
rl.question("请输入星期几: ", (day) => {
switch(day){
case "1":
console.log("今天吃炒面");
break;
case "2":
console.log("今天吃鱼香肉丝");
break;
case "3":
console.log("今天吃麻辣香锅盖饭");
break;
case "4":
console.log("今天吃豆丁胡萝卜");
break;
case "5":
console.log("今天公司聚餐");
break;
case "6":
console.log("今天吃泡面");
break;
case "7":
console.log("今天撸串");
break;
default:
console.log("input error.")
} rl.close();
});
rl.on("close", function () {
process.exit();
});

  2.循环语句

  for 循环

和java中的for循环一致:for(exp1; exp2; exp3){代码块;}
  - exp1: 无条件的执行第一个表达式
  - exp2: 是判断是否能执行循环体的条件
  - exp3: 增量操作
// 九九乘法表
var str = "";
for(var i=1;i<=9;i++){
for(var j=1;j<=i;j++){
str += i + "*" + j + "=" + i*j + " ";
if(i === j){
str += "\n";
}
}
}
console.log(str);

  while 循环

var arr = function (number) {
var arr_list = new Array(); // var arr_list = [];
var i = 0;
while (i < number){
arr_list[i] = Math.random();
i++;
}
return arr_list;
};
console.log(arr(5))
var arr = function (number) {
var arr_list = new Array(); // var arr_list = [];
var i = 0;
while (i < number){
arr_list[i] = Math.random();
i++;
}
return arr_list;
};
console.log(arr(5));

  do ... while循环


// 和java中的do ... while 循环一致,先执行依次do内的代码块,再执行while 判断。不管while条件判断是否成功,do都会至少执行一次。
var arr = function (number) {
var arr_list = new Array(); // var arr_list = [];
var i = 0;
do {
arr_list[i] = Math.random();
i++;
}while (i > number);
return arr_list;
};
console.log(arr(5));

三、函数

  1.定义

  函数通过function关键字定义。function 函数名称([参数1, ...]){代码块; [return 返回值]};也可以通过Function构造器定义函数。


// 通过function 关键字定义函数
function hello() {
console.log("hello world.")
};
hello();

  匿名函数,即function关键字定义的无函数名称的函数。

// 通过function 关键字定义匿名函数
var hello = function () {
console.log("hello world.")
};
hello();

  将匿名函数作为参数,传递给另一个函数进行执行,此时其被称为回调函数。回调函数在js中异常强大。

function calc(v1, v2, callback) {
v1 = v1 || 1;
v2 = v2 || 2;
return callback(v1, v2);
}
calc(3,4, function (v1, v2) {
return v1 + v2
});

  

  2.参数

  函数如果定义了参数,在调用函数的时候没有传值则默认值为undefined。如果传递的参数超过了形参,js会忽略掉多于的参数值。

function  calc(v1, v2){
return v1 + v2;
}
console.log(calc(5, 6, 7));

  es5不能直接写形参的默认值,但可以通过arguments对象来实现默认值。同时,arguments对象可以实现可变参数。

function  calc(v1, v2){
v1 = v1 || 1;
v2 = v2 || 2;
return v1 + v2;
}
console.log(calc());

  3.函数调用

function calc(v1, v2, callback) {
v1 = v1 || 1;
v2 = v2 || 2;
return callback(v1, v2);
}
value1 = calc(3,4, function (v1, v2) {
return v1 + v2
}); value2 = calc.call(calc, 3, 4, function (v1, v2) {
return v1 + v2;
}); value3 = calc.apply(calc, [3, 4, function (v1, v2) {
return v1 + v2;
}]); value4 = (function (v1, v2) {
return v1 + v2;
})(3, 4);
console.group("函数调用的方式");
console.log("- 直接调用: " + value1);
console.log("- 间接call调用: " + value2);
console.log("- 间接apply调用: " + value3);
console.log("- 自调用: " + value4);

四、对象

  js中对象分为:内建对象、宿主对象和自定义对象。

  1.对象创建

  直接通过var关键字定义Object对象。

var obj1 = new Object();
var obj2 = {};
// 使用字面量来创建一个对象: var obj = {} 和new本质上是一模一样的
// 使用字面量创建对象时,可以在创建对象时直接指定对象中的属性
// 字面量里面的属性可以加引号,也可以不加引号,建议不加
// 如果使用特殊字符或名字则必须加引号
var obj = {
name: "孙悟空",
gender: "男猴",
age: 1500,
credit: {
name1: "孙行者",
name2: "齐天大圣"
}
};
console.log(obj);

  也可以通过工厂方法创建对象。

function Person(name, age) {
var obj = {};
obj.name = name;
obj.age = age;
obj.sayHello = function () {
console.log(obj.name + ", " + obj.age + "years old.");
};
return obj;
}
sun = Person("孙悟空", 2000);
sun.sayHello();

  2.对象属性操作和方法创建


var obj = new Object(); // new 构造对象, 可使用typeof obj 查看对象
// 在对象中保存的值称为属性
// 向对象中添加属性:对象.属性名 = 属性值
obj.name = "孙悟空";
obj.gender = "男猴";
obj.age = 18;
console.log(obj);
// 读取对象中的属性: 对象.属性名
// 如果读取的对象中没有该属性,会返回undefined
console.log(obj.name);
// 修改对象的属性值: 对象.属性名 = 新值
obj.age = 24;
console.log(obj);
// 删除对象属性
delete obj.age;
console.log(obj);
// 自定义
obj.fuc = function add(x, y) {
return x+y;
};
console.log(obj);

  3.作用域

在js中一共有两种作用域,全局作用域和函数作用域
全局作用域:
- 直接编写在script标签内的JS代码
- 在页面打开时创建,在页面关闭时销毁
- 在全局作用域中有一个全局对象window,可以直接使用.它代表的是一个浏览器的窗口,它由浏览器创建
- 在全局作用域中创建的变量都会作为window对象的属性保存
- 在全局作用域中创建的函数都会作为window对象的方法保存
- 全局作用中的变量和函数在页面的任意位置都可以被访问/执行
  函数作用域:
  - 调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁
  - 每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的
  - 全局作用域中访问不到函数作用域,函数作用域中可以访问全局作用域
   - 函数作用域会优先查找本作用域中的变量,如果没有就找上一级中的变量
  - 函数作用域的a并不影响上一级作用域中的a
- 如果不使用var声明,直接写a = 20,就是在操作全局作用域中的a变量
- 如果使用全局作用域中的a变量[在本作用域中已声明a变量],可以用window.a,这在b1中已强调过

  全局作用域

console.log(window); // window是个对象

// 使用var关键字声明的变量,会在所有的代码执行之前执行;如果声明变量时不使用var,则变量不会被提前声明
console.log(a); // 此时的var a已被声明,它的值是undefined,到下一行时它的值才会是123 var a = 123; // 它相当于window.a = 123
console.log(window.a); console.log(abc()); // 可以提前声明和执行
console.log(abc2()); // var提前声明的是一个undefined的window属性,不是个函数: abc2 is not a function // 使用function关键字声明的函数,和var的机制一样,是函数声明的提前,它会提前(优先)执行
function abc() { // 它相当于window.abc = function (){console.log("abc")}
console.log("abc");
}
console.log(window.abc()); // 使用函数表达式不会被声明提前
var abc2 = function() {
console.log("abc2");
}

  局部作用域

var a = 19;
var b = 30;
function fun() {
a = 20;
var b = 1000;
console.log("a = " + a); // 这里打印的是20
console.log("b = " + b); // 这里打印的是1000
console.log("window.b = " + window.b); // 这里打印的是30
}
fun();
console.log(a); // 这里打印的是20
// 定义形参相当于在函数作用域中声明了变量

五、原型

  1.this关键字

解析器在调用函数时,会向函数内部传递进一个隐含的参数这个隐含的参数就是this,this指向的是一个对象,这个对象称为函数执行的上下文对象
根据函数的调用方式不同,this会指向不同的对象
- 1.以函数的形式调用时,this永远都是window
- 2.以方法的形式调用时,this就是调用方法的那个对象
var name = "全局名字";
function func(a, b) {
console.log("a = " + a + ", b = " + b);
console.log(" Object: " + this);
console.log(this);
}
func(123, 456); // this指的是window
function func2() {
console.log(this.name);
console.log(this);
}
var obj = {
name: "孙悟空",
sayName: func, // 把函数赋给属性,this指的是obj
sayName2: func2 };
var obj2 = {
name: "猪八戒",
sayName: func, // this指的是obj2
sayName2: func2
};
obj2.sayName(2332, 4523);
obj.sayName(234, 789);
obj.sayName2(); // this可以支持对象内部的函数去访问对象内部的属性
obj2.sayName2(); // 这一点特别像python类中的self

var obj3 = {
name: "沙和尚",
teacher: "唐僧",
address: "流沙河",
sayMyTeacher: function3,
sayMySelf: function2,
say: function1
};
function function1() {
var say = this.sayMySelf() + this.sayMyTeacher();
console.log(say);
}
function function2() {
var say = "大家好,我是" + this.name + ",我老家是" + this.address;
return say
}
function function3() {
var say = "。我的师父是" + this.teacher + "老师, 他是个得道高僧";
return say
}
obj3.say();

  2.构造方法的重写


function Person1(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
// this.sayName = function() {
// console.log("大家好,我系" + this.name); // 这样写每创建一个对象,就会创建一个sayName
// }
this.sayName = sayName; // 共用同一个方法,它就相当于python中的类方法[类方法只有一份,但每个实例对象都共用]
} // 注意这里的写法,一个隐含的this传递给了sayName函数
var per1 = new Person1("孙悟空", 18, "男");
per1.sayName(); // 在全局作用域中写sayName
// 但是它污染了全局作用域的命名空间,也就是全局作用域不能再写sayName函数
// 另外这个函数也很不安全,由此引出了"原型"的概念
function sayName() {
console.log("大家好,我系" + this.name);
}

  3.原型

  1.原型prototype

我们所创建的每一个函数,解析器都会向函数中添加一个属性:prototype
如果函数作为普通函数调用prototype,没有任何作用
当该函数以构造函数的形式调用[per1]时,它[per1]会有一个隐含的属性__proto__指向其原型对象[Person]
每次调用时都会有各自的__proto__指向原型对象的prototype,也就是原型对象中的属性和方法被调用函数"共享"
function Person() {}
console.log(Person.prototype); var per1 = new Person();
console.log(per1.__proto__ == Person.prototype); // true Person.prototype.a = "我是原型对象中的123456";
per1.a = "我是mc中的" +"123456"; var per2 = new Person();
console.log(per1.a); // 找到调用函数的属性和方法,直接执行
console.log(per2.a); // 如果调用函数没有该属性或方法,会从原型对象中寻找 Person.prototype.sayName = function() {
console.log('我是原型对象的sayName');
};
per2.sayName = function() {
console.log('我是per2中的sayName');
};
per1.sayName(); // 和前面的类似
per2.sayName(); // 和前面的类似
// 解决全局作用域污染问题: 把对象的函数写在prototype里而不是全局作用域里
function MyPerson(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
MyPerson.prototype.sayName = function() {
console.log("大家好,我系" + this.name);
};
var mp1 = new MyPerson("孙悟空", 2000, "男猴");
mp1.sayName();

  2.原型模拟类和对象

  在python中声明一个类和对象:

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
  def sayHello(self):
    print("{}, {} years old.".format(self.name, self.age)) sun = Person("孙悟空", 2000)
sun.sayHello() // 对象可以调用方法,因为方法只有一份且存在类内存中,每个对象只保留了引用
Person.sayHello(sun) // 类可以传入一个对象来调用方法,因为方法存在类内存中

  在Java中创建一个类和对象:类的方法存在方法区,对象存在堆内存中,多个对象共用它们父类的方法。它需要设置静态方法来实现对象调用。

public class Person {
private String name;
private int age;
Person(String name, int age){
  this.name = name;
  this.age = age;
  }  
  public void sayHello(){
  System.out.println(this.name + ", " + this.age + "years old.");
  }
  public static void sayHello(Person obj){
  System.out.println(obj.name + ", " + obj.age + "years old.");
  }
  public static void main(String[] args){
  Person sun = new Person("孙悟空", 2000);
  Person.sayHello(sun);
  sun.sayHello();
  }
}

  在js中,对象保存在堆内存中,每创建一个新的对象都会开一个堆内存空间,并把其属性和方法都保存在堆内存中。注意,如果不用原型,每个对象都会将其方法复制一份到自己的堆内存空间中。js中实现类调用实例对象:

function MyPerson(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
MyPerson.sayName = MyPerson.prototype.sayName = function (obj) { // 在自己的prototype空间里写函数
obj = obj || this;
console.log("大家好,我系" + obj.name + ", 一只火眼金睛的" + obj.gender); // 让每个实例都能访问
}
}
var mp1 = new MyPerson("孙悟空", 2000, "男猴"); // 注意这里使用的是new MyPerson,构造
mp1.sayName();
MyPerson.sayName(mp1);

前端(三):JavaScript基础的更多相关文章

  1. 第三篇:web之前端之JavaScript基础

    前端之JavaScript基础   前端之JavaScript基础 本节内容 JS概述 JS基础语法 JS循环控制 ECMA对象 BOM对象 DOM对象 1. JS概述 1.1. javascript ...

  2. 前端之JavaScript基础

    前端之JavaScript基础 本节内容 JS概述 JS基础语法 JS循环控制 ECMA对象 BOM对象 DOM对象 1. JS概述 1.1. javascript历史 1992年Nombas开发出C ...

  3. 前端见微知著JavaScript基础篇:你所不知道的apply, call 和 bind

    在我的职业生涯中,很早就已经开始使用JavaScript进行项目开发了.但是一直都是把重心放在了后端开发方面,前端方面鲜有涉及.所以造成的一个现象就是:目前的前端知识水平,应付一般的项目已然是足够的, ...

  4. 前端-JavaScript2-1——JavaScript基础复习及上次作业答案

    昨天讲解的JS是编程最最简单的一些基础知识,复习一下: JavaScript书写环境,<script>标签 1    <script type=”text/javascript”&g ...

  5. 谷哥的小弟学前端(10)——JavaScript基础知识(1)

    探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 具体解释Android主流框架不可或缺的基石 站在源代码的肩膀上全解Scroller工作机制 Android多分辨率适 ...

  6. 前端之JavaScript基础及使用方法

    JavaScript概述 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECM ...

  7. 前端见微知著JavaScript基础篇:this or that ?

    上节,我们提到了this关键字的问题,并且追加了一句很有意义的话:谁调用我,我指向谁.的确,在javascript中,在默认情况下,this会指向一个已经初始化的window对象.所以你不论有多少全局 ...

  8. 前端--关于javascript基础

    首先javascript不是浏览器的附属品,只能说它大多数的运行环境是在浏览器中的,但又不仅仅局限于浏览器中.它是一门真正的程序设计语言,在这方面它和java.c.c++.c#是等同的,只不过它不直接 ...

  9. 谷哥的小弟学前端(11)——JavaScript基础知识(2)

    探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 具体解释Android主流框架不可或缺的基石 站在源代码的肩膀上全解Scroller工作机制 Android多分辨率适 ...

  10. Web前端开发JavaScript基础

    JavaScript 一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型,它的解释器被称为JavaScript引擎,是浏览器的一部分,并且是被广泛用于客户端的脚本语言,JavaS ...

随机推荐

  1. 浅谈Android选项卡(二)

    前面简单介绍了选项卡,下面以及后面的几篇文章介绍下Android选项卡的几种简单实现方法. http://blog.csdn.net/xia215266092/article/details/9613 ...

  2. Mac下显示和隐藏“隐藏文件”

    命令行方式:显示/隐藏Mac隐藏文件命令如下(注意其中的空格并且区分大小写): 显示Mac隐藏文件的命令: defaults write com.apple.finder AppleShowAllFi ...

  3. vue-cli中的webpack打包配置

    如下: assetsSubDirectory: 'static', assetsPublicPath: '/projectName/', 其中assetsSubDirectory是代表服务器上的实际路 ...

  4. 题目1021:统计字符(hash简单应用)

    问题来源 http://ac.jobdu.com/problem.php?pid=1021 问题描述 每次输入两个字符串,统计第一个字符串中的每个字符在第二个字符串中出现的次数. 问题分析 太明显了, ...

  5. Linux新手随手笔记1.9-使用Apache搭建网站

    搭建网站 网站服务:让用户能够通过浏览器访问到的服务器上的文档资源. 对比Windows 和Linux部署服务方法对比 Windows:IIS Linux      :Apache ,nginx Ap ...

  6. TCP/IP——何时用UDP代替TCP

    UDP和TCP UDP和TCP都有其自身的特点,不同的应用场景和要求需要使用不同的协议来传输,那么何时我们可以用UDP代替TCP呢. UDP 的优点 UDP支持广播和多播,事实上如果应用程序使用广播或 ...

  7. [NodeJS]Jenkins-cli

    使用npm 包nestor 触发jenkins job, 达到命令行管理Jenkins功能. 1. install nestor : npm install -g nestor 2. set JENK ...

  8. 常见浏览器hack汇总

    1.背景渐变bug: ①.ie8 ie9:用滤镜的方式解决: -ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientT ...

  9. USART列子

    #include "stm32f10x.h" void USART_INit(void) { GPIO_InitTypeDef GPIO_Initstructe; USART_In ...

  10. springboot(十)-监控应用

    微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台的业务流会经过很多个微服务的处理和传递,出现了异常如何快速定位是哪个环节出现了问题? ...