前端(三):JavaScript基础

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 -> NaNvar b = 1;a = null; // null -> 0a = false; // false -> 0a = "123"; // "12" -> 12a = "123abc"; // "123abc" -> NaNconsole.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:exp3var 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);// 读取对象中的属性: 对象.属性名// 如果读取的对象中没有该属性,会返回undefinedconsole.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 = 123console.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指的是windowfunction 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() { // 在自己的prototype空间里写函数        console.log("大家好,我系" + this.name); // 让每个实例都能访问,这才是标准的类方法       }}var mp1 = new MyPerson("孙悟空", 2000, "男猴");   // 注意这里使用的是new MyPerson,构造mp1mp1.sayName();   // 原型对象也有__proto__属性,也会指向原型对象的原型中的prototype// 原型对象的顶层就是Object的对象: obj1.__proto__.__proto__.__proto__ ...

   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);

原文地址:https://www.cnblogs.com/kuaizifeng/p/9293408.html

时间: 2024-08-30 06:43:02

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

前端之JavaScript基础

前端之JavaScript基础 本节内容 JS概述 JS基础语法 JS循环控制 ECMA对象 BOM对象 DOM对象 1. JS概述 1.1. javascript历史 1992年Nombas开发出C-minus-minus(C-)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言) Netscape(网景)接收Nombas的理念,(Brendan Eich)在其Netscape Navigator 2.0产品中开发出一套livescript的脚本

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

在我的职业生涯中,很早就已经开始使用JavaScript进行项目开发了.但是一直都是把重心放在了后端开发方面,前端方面鲜有涉及.所以造成的一个现象就是:目前的前端知识水平,应付一般的项目已然是足够的,但是火候尚缺,没有深入的进行研究,以至于总是谈论起来就发现自己半瓶子哐当的水平.为了解决这种尴尬的局面,决心潜心研究一段时间JavaScript,以下知识为本人学习过程中的总结,虽然以本人水平可能招致贻笑大方之果,但是更盼抛砖引玉之实. 在JavaScript中,我们调用一个普通的方法,可以通过如下

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

上节,我们提到了this关键字的问题,并且追加了一句很有意义的话:谁调用我,我指向谁.的确,在javascript中,在默认情况下,this会指向一个已经初始化的window对象.所以你不论有多少全局变量,全局函数,默认都是追加到window对象上,所以在这种情况下无论怎么使用this,都是在这个window对象上去查找各种变量,函数等. 在实际编码中,this的默认情况只能适用于业务比较简单的场景中.但是在大部分业务场景中,this都需要改变其指向来实现一定的业务逻辑.这样一来,我们就得来好好

前端javaScript基础学习第三天

目前在从事前端工作,特别总结javaScript基础知识供大家学习,本人特总结一下使用方法献给目前正在学习web前端的小伙伴们,希望你们在前端领域闯出属于自己的一片天空来,需要sublime软件安装包的或者前端资料的可以留言 一.循环语句循环语句:重复执行一段代码,执行遇见某个指令(条件为假),结束循环语句 for循环,do while, while, for in语句 2.1 for循环语句 for循环是前测试循环语句:先判断条件是否满足,当满足条件时,才执行循环语句.直到条件为假结束循环语句

菜鸟学前端--javascript基础

在学习过css相关的知识,有了前端工程师的一些基础知识.但要较好的掌握前端,必须要学习好javascript的知识. 下面将从基本语法.变量.关键字.保留字.语句.函数.BOM等角度阐释. 一.基本语法 javacript作为一种面向对象的.脚本级的轻量语言,与java一脉相承. 命名:区分大小写,弱类型定义(一般采用var,不限制类型). 行末分号可有可无(从经验上来看,推荐写,可以提高代码阅读质量). 括号用于代码段. 注释与C.java类型,单行用"//",段注释用"/

javascript基础学习(三)

javascript之运算符 学习要点: 表达式 运算符:一元运算符,算术运算符,关系运算符,逻辑运算符,*位运算符,赋值运算符 一.表达式 表达式有常量表达式,变量表达式,复合表达式. 二.算术运算符 一元:+(正号).-(负号).++.—— 二元:*./.%.+.- 三.关系运算符 ==.=== ps:等同运算符比相等运算符要求更为严格,等同运算符只有在两个操作数类型相同,并且值也相同的情况下才会返回true. <.<=.>.>= instanceof运算符.       in

web前端【第五篇】JavaScript基础

一.JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言) Netscape(网景)接收Nombas的理念,(Brendan Eich)在其Netscape Navigator 2.0产品中开发出一套livescript的脚本语言.Sun和Netscape共同完成.后改名叫Javascript 微软随后模仿在其IE3.0的产品中搭载了一个JavaScript的

JavaScript基础三

1.10 关于DOM的事件操作 1.10.1 JavaScript的组成 JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:文档对象模型,操作网页上的元素的API.比如让盒子移动.变色.轮播图等. BOM:浏览器对象模型,操作浏览器部分功能的API.比如让浏览器自动滚动. 1.10.2 事件 JS是以事件驱动为核心的一门语言. 事件的三要素 事件的三要素:事件源.事件.事件驱动程序. 比

web前端javaScript基础第六天

目前在从事前端工作,特别总结javaScript基础知识供大家学习,本人特总结一下使用方法献给目前正在学习web前端的小伙伴们,希望你们在前端领域闯出属于自己的一片天空来,需要sublime软件安装包的或者前端资料的,可以加我创建的前端群 937268047 函数:变量作用域:js只有函数能够关住变量的作用域全局变量局部变量:在函数内部声明的变量,只能在函数内部使用 函数的形参是局部变量,形参只能在函数内部使用全局变量作用:一个变量可以被多个函数改变,这个变量一定是全局变量(信号量) 函数作用域

JavaScript基础(三)

JavaScript基础(三) for循环嵌套 循环嵌套不是什么特殊语法,就是说js中的许多语法结构都可以嵌套使用,for也可以 循环嵌套时,代码执行次数变多,通常使用是在2层左右 while循环 规则: 先进行条件检测,如果为true,执行循环体代码 再检测条件,再为true再执行循环体,以此类推 直到条件为false时循环结束 while (条件) { // 循环体 } for和while的使用场景 for循环适用于次数确定的重复操作(for使用较多) while循环适用于不确定次数的重复操