第一章 JavaScript基础语法
一、字面量(编程语言中的固定量)
1.数字(Number)
可以为整数,小数,科学计数(e)等等
2.字符串(String)
3.表达式
用于计算的固定值。3 + 2.2,3.14 * 2等
4.数组(Array)
5.对象(Object)
定义一个对象
在JavaScript中,对象(Object)是一种复杂的数据类型,用于存储键值对(key-value pairs)集合。对象中的每个键值对都可以看作是一个属性(property),其中键(key)是属性名(字符串),值(value)可以是任意数据类型,包括数字、字符串、布尔值、数组、函数甚至是另一个对象。
创建对象字面量:使用花括号
{}
直接创建对象,并在内部定义属性和方法。
let person = {
firstName: "John",
lastName: "Doe",
age: 30,
greet: function(){
console.log("Hello, my name is" + this.firstName + " " + this.lastName);
}
}
6.函数(Function)
二、JavaScript变量
JavaScript用关键字var来定义变量:
var y = false; //布尔值
var length = 15.88; //数字
var points = x * 10; //表达式
var lastName = "Johnson"; //字符串
var cars = ["Saab", "Volvo", "BMW"]; //数组
var person = {firstName: "Jhon", lastName: "Doe"}; //对象字典
JavaScript变量分为两种:
1.全局变量:
在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它
2.局部变量:
在JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它
非严格模式下给未声明变量赋值创建的全局变量,是全局对象的可配置属性,可以删除。
var var1 = 1;//不可配置全局变量 var2 = 2;//没有使用var声明,可配置全局属性 console.log(this.var1);//1 console.log(window.var1);//1 delete var1;//false 无法删除 console.log(var1);//1 delete var2; console.log(delete var2);//true console.log(var2);//已经删除 报错变量未定义
三、JavaScript引用与输出
1.JavaScript的引用
1.1标签引用
在HTML中在script标签中就可以编写JavaScript代码。
<script> alert("Hello World"); </script>
1.2文件引用
在一个单独的js文件中也可以编写JavaScript代码,然后在HTML文件中使用script标签进行引用。
main.html
<script src="main.js"></script>
main.js
alert("Hello World");
2.JavaScript的输出
2.1页面输出
用JavaScript向页面输出一段话:
<script>document.write("Hello World!");</script>
2.2控制台输出
用JavaScript向控制台输出一段话:
<script> console.log("输出一条日志");//最常用 console.info("输出一条信息"); console.warn("输出一条警告"); console.error("输出一条错误"); </script>
2.3弹出窗口输出
用JavaScript向弹出窗口输出一段话:
<script> alert("Hello World!"); </script>
四、JavaScript函数
1.创建函数
-
使用 函数对象 来创建一个函数(几乎不用)
var fun = new Function("console.log('这是我的第一个函数');");
-
使用 函数声明 来创建一个函数(比较常用)
function fun(){ console.log("这是我的第二个函数"); }
-
使用 函数表达式 来创建一个函数(比较常用)
var fun = function(){ console.log('这是我的第三个函数'); }
2.函数调用
-
对于无参函数调用
// 函数声明 var fun = function () { console.log("哈哈,我执行啦!"); } // 函数调用 fun();
-
对于有参函数调用
// 函数声明 var sum = function (num1, num2) { var result = num1 + num2; console.log("num1 + num2 = " + result); } // 函数调用 sum(10, 20);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是一个JavaScript网站</title>
</head>
<body>
<h1>
函数参数传递问题
</h1>
<p>
点击下面按钮调用
</p>
<button onclick="myFunc('Mike', '18', 'Beijing')">
点击这里
</button>
<script>
function myFunc(name, age, address){
alert("My name is " + name + ", age is " + age + "and my address is in "+address);
}
</script>
</body>
</html>
上面是一个基本的在由HTML编写的网页里定义JavaScript函数并调用时实例
实例:计算两个数的乘积并返回结果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript网站</title>
</head>
<body>
<h1>
计算两个数的值返回
</h1>
<p id="demo"></p>
<script>
function myFunction(a, b) {
return a * b;
}
document.getElementById("demo").innerHTML = myFunction(5, 6);
</script>
</body>
</html>
语句
JavaScript语句向浏览器发出的命令,告诉浏览器该做什么。下面的JavaScript语句向id="demo"的 HTML元素输出文本"Hello World!" :
document.getElementById("demo").innerHTML = "Hello World!";
2.1匿名函数
没有名字的函数就是匿名函数,它可以让一个变量来接收,也就是用 “函数表达式” 方式创建和接收。
var fun = function () {
alert("我是一个匿名函数");
}
fun();
2.2立即执行函数
函数定义完,立即被调用,这种函数叫做立即执行函数,立即执行函数往往只会执行一次。
(function (){
alert("我是一个立即执行函数");
})();
2.3对象中的函数
对象的属性值可以是任何的数据类型,也可以是个函数。
如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象的方法,调用这个函数就说调用对象的方法(method)。
var person = {
name: "张智",
age: "20",
sex: "男",
sayHello: function () {
console.log(name + " hello");
}
}
person.sayHello();
五、对象
1.对象基础
1.1概述
Object类型,我们也称为一个对象,是JavaScript中的引用数据类型。它是一种复合值,它将很多值聚合到一起,可以通过名字访问这些值。对象也可以看做是属性的无序集合,每个属性都是一个名/值对。对象除了可以创建自有属性,还可以通过从一个名为原型的对象那里继承属性。除了字符串、数字、true、false、null和undefined之外,JavaScript中的值都是对象。
1.2创建对象
-
第一种方式
var person = new Object(); person.name = "杨帅"; person.age = 21; console.log(person);
-
第二种方式
var person = { name: "杨帅", age: 21 }; console.log(person);
1.3访问属性
-
第一种方式
对象名.属性名
-
第二种方式
对象名['属性名']
1.4删除属性
案例演示:
var person = new Object();
person.name = "杨帅";
person.age = 21;
console.log(person);
delete person.name
console.log(person);
1.5遍历对象
枚举遍历对象中的属性,可以使用for … in语句循环,对象中有几个属性,循环体就会执行几次。
语法:
for(var 变量 in 对象){ }
案例:
var person = { name: "杨帅", age: 21 }; for(var personKey in person){ var personVal = person[personKey]; console.log(personKey + ":" + personVal); }
2.对象进阶
2.1 用工厂方法创建对象
工厂方法(Factory Method)是一种设计模式,它属于创建型模式的一种。在工厂方法中,我们不直接实例化对象,而是通过调用一个工厂方法来获取新对象。这个工厂方法可以根据传入的参数或者当前的环境来决定具体实例化哪一个类。
Q:已经知道如何创建一个对象,那要是想要创建多个对象又该怎么办?
A:那有多少个就创建多少个呗!
var person1 = {
name: "孙悟空",
age: 18,
sayName: function () {
console.log(this.name);
}
};
var person2 = {
name: "猪八戒",
age: 19,
sayName: function () {
console.log(this.name);
}
};
var person3 = {
name: "沙和尚",
age: 20,
sayName: function () {
console.log(this.name);
}
};
console.log(person1);
console.log(person2);
console.log(person3);
Q:上述代码没错,但是只仅限于少量对象,假设说要用循环创建1000个对象该怎么办?
A:那可以用以下代码:
//使用工厂模式创建对象
function createPerson(){
//创建新的对象
var obj = new Object();
//设置对象属性
obj.name = "杨帅";
obj.age = 21;
//设置对象方法
obj.sayName = function(){
console.log(this.name);
};
//返回新的对象
return obj;
}
var person1 = createPerson();
var person2 = createPerson();
var person3 = createPerson();
console.log(person1);
console.log(person2);
console.log(person3);
Q:上述代码看起来更加简洁,但是你会发现每一个人都是杨帅,我们要是想要给每一个人不同的属性值呢?
A:
//使用工厂模式创建对象
function createPerson(){
//创建新的对象
var obj = new Object();
//设置对象属性
obj.name = name;
obj.age = age;
//设置对象方法
obj.sayName = function(){
console.log(this.name);
};
//返回新的对象
return obj;
}
var person1 = createPerson("张智", 20);
var person2 = createPerson("杨帅", 21);
var person3 = createPerson("诸葛", 23);
var person4 = createPerson("周晨超", 21);
console.log(person1);
console.log(person2);
console.log(person3);
Q:现在再看上述代码,发现好像已经完美的解决了创建多个对象的难题,那我们是不是可以用循环批量创建1000个对象了呢?
A:
// 使用工厂模式创建对象
function createPerson(name, age) {
// 创建新的对象
var obj = new Object();
// 设置对象属性
obj.name = name;
obj.age = age;
// 设置对象方法
obj.sayName = function () {
console.log(this.name);
};
//返回新的对象
return obj;
}
for(var i=0;i<=1000;i++){
var person = createPerson("person" + i, 18);
console.log(person);
}
这样我们就实现了批量创建对象的功能,至于对象的名称和年龄,我们可以通过名称数组和年龄数组来获取
2.2 用构造函数创建对象
使用工厂模式创建对象,但是会发现创建出来的对象的对象类型都是Object。
那这有问题吗?看起来有,看起来好像又没有,每创建一个都是对象,但是在实际生活中,人应该是一个确定的类别,属于人类,对象是一个笼统的称呼,万物皆对象,它并不能确切的指明当前对象是人类,那我们要是既想实现创建对象的功能,同时又能明确所创建出来的对象是人类,那么似乎问题就得到了解决,这就用到了构造函数,每一个构造函数你都可以理解为一个类别,用构造函数所创建的对象我们也成为类的实例,那我们来看看是如何做的:
// 使用构造函数来创建对象
function Person(name, age) {
// 设置对象的属性
this.name = name;
this.age = age;
// 设置对象的方法
this.sayName = function () {
console.log(this.name);
};
}
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙悟净", 20);
console.log(person1);
console.log(person2);
console.log(person3);
- 当以函数的形式调用时,this是window
- 当以方法的形式调用时,谁调用方法this就是谁
- 当以构造函数的形式调用时,this就是新创建的那个对象
2.3 原型
学习了使用构造函数的方式进行创建对象,但是,它还是存在一个问题,那就是,你会发现,每一个对象的属性不一样这是一定的,但是它的方法似乎好像是一样的,如果我创建1000个对象,那岂不是内存中就有1000个相同的方法,那要是有10000个,那对内存的浪费可不是一点半点的,我们有没有什么好的办法解决,没错,我们可以把函数抽取出来,作为全局函数,在构造函数中直接引用就可以了。
//构造函数创建对象
function Person(name, age){
//设置对象属性
this.name = name;
this.age = age;
//设置对象方法
this.sayName = sayName;
}
//抽取方法为全局函数
function sayName(){
console.log(this.name);
}
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙悟净", 20);
person1.sayName();
person2.sayName();
person3.sayName();
但是,在全局作用域中定义函数却不是一个好的办法,为什么呢?因为,如果要是涉及到多人协作开发一个项目,别人也有可能叫sayName这个方法,这样在工程合并的时候就会导致一系列的问题,污染全局作用域,那该怎么办呢?有没有一种方法,我只在Person这个类的全局对象中添加一个函数,然后在类中引用?答案肯定是有的,这就需要原型对象了。
//构造函数创建对象
function Person(name, age){
//设置对象属性
this.name = name;
this.age = age;
}
Person.peototype.sayName = function(){
console.log(this.name);
}
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙悟净", 20);
person1.sayName();
person2.sayName();
person3.sayName();
原型:
在js中,每一个函数类型的数据,都有一个叫做prototype的属性,这个属性指向的是一个对象,就是所谓的原型对象。对于原型对象来说,它有一个constructor属性,指向它的构造函数。
-
原型对象:用于存放实例对象的公有属性和公有方法
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.species = '人类'; Person.prototype.say = function () { console.log("Hello"); } let per1 = new Person('xiaoming', 20); let per2 = new Person('xiaohong', 19); console.log(per1.species); // 人类 console.log(per2.species); // 人类 per1.say(); // Hello per2.say(); // Hello
可是这里的species属性和say方法不是实例对象自己的,为什么可以直接用点运算符访问?这是因为在js中,对象如果在自己的这里找不到对应的属性或者方法,就会查看构造函数的原型对象,如果上面有这个属性或方法,就会返回属性值或调用方法。所以有时候,我们会用per1.constructor查看对象的构造函数:
console.log(per1.constructor); // Person()
2.4 原型链
2.4.1 显示原型
利用prototype属性查找原型,只是这个是函数类型数据的属性。
2.4.2 隐式原型
利用____proto____属性查找原型,这个属性指向当前对象的构造函数的原型对象,这个属性是对象类型数据的属性,所以可以在实例对象上面使用:
console.log(per1.__proto__ === Person.prototype);//true
console.log(per2.__proto__ === Person.prototype);//true
2.4.3 原型链
原型对象也是对象,那它就也会有原型,那它的____proto____就会指向它的构造函数的原型对象。而在js中,对象的构造函数就是Object(),所以原型对象的原型对象就是Object.prototype,但是Object.prototype没有上一层的原型对象,所以它的proto指向的就是null。
如果某个对象查找属性,自己和原型对象上都没有,那就会继续往原型对象的原型对象上去找,这个例子里就是Object.prototype,这里就是查找的终点站了,在这里找不到,就没有更上一层了(null里面啥也没有),直接返回undefined。
可以看出,整个查找过程都是顺着__proto__属性,一步一步往上查找,形成了像链条一样的结构,这个结构,就是原型链。所以,原型链也叫作隐式原型链。
2.5 toString方法
toString()函数用于将当前对象以字符串的形式返回。该方法属于Object对象,由于所有的对象都"继承"了Object的对象实例,因此几乎所有的实例对象都可以使用该方法,所有主流浏览器均支持该函数。
// 使用构造函数来创建对象 function Person(name, age) { // 设置对象的属性 this.name = name; this.age = age; } //创建对象的一个实例对象 var p = new Person("张三", 20); console.log(p.toString());
2.6 hasOwnPeoperty方法
判断当前对象是否包含指定的属性或方法可以使用 in 运算符来检查:
//创造一个构造函数
function MyClass(){
}
//向MyClass的原型中添加一个name属性
MyClass.prototype.name = "原型中的名字";
//创建一个MyClass实例
var mc = new MyClass();
mc.age = 18;
//使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
console.log("age" in mc);//true
console.log("name" in mc);//true
如果我只想要检查自身对象是否含有某个方法或属性,我们可以使用Object的hasOwnProperty()方法,它返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
// 创造一个构造函数
function MyClass() {
}
// 向MyClass的原型中添加一个name属性
MyClass.prototype.name = "我是原型中的名字";
// 创建一个MyClass的实例
var mc = new MyClass();
mc.age = 18;
// 可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性,使用该方法只有当对象自身中含有属性时,才会返回true
console.log(mc.hasOwnProperty("age"));//true
console.log(mc.hasOwnProperty("name"));//false
这个方法是Object中特有的方法
// 创造一个构造函数
function MyClass() {
}
// 向MyClass的原型中添加一个name属性
MyClass.prototype.name = "我是原型中的名字";
// 创建一个MyClass的实例
var mc = new MyClass();
mc.age = 18;
// 检查当前对象
console.log(mc.hasOwnProperty("hasOwnProperty"));//false
// 检查当前对象的原型对象
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));//false
// 检查当前对象的原型对象的原型对象
console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true
2.7 对象继承
区别于Java等面向对象语言,JavaScript中并没有类的概念,因此JavaScript的对象也与基于类的对象有所不同。所以JavaScript是通过原型来实现面向对象编程的。
JavaScript有六种经典的对象继承方式:
- 原型链继承
- 借用构造函数继承
- 组合继承
- 原型式继承
- 寄生式继承
- 寄生式组合继承
主要学习前三个
2.7.1 原型链继承
核心思想:子类型的原型为父类型的一个实例对象
基本做法:
- 定义父类型构造函数
- 给父类型的原型添加方法
- 定义子类型的构造函数
- 创建父类型的对象赋值给子类型的原型
- 将子类型原型的构造属性设置为子类型
- 给子类型原型添加方法
- 创建子类型的对象: 可以调用父类型的方法
//定义父类构造函数
function Father(){
this.name = "father";
}
//在父类的原型上定义方法
Father.prototype.getName = function(){
return this.name;
}
//定义子类构造函数
function Child(){
this.name = "child";
}
//子类继承父类
Child.prototype = new Father();
//实例化
var child1 = new Child();
console.log(child1.getName());//child
缺点:原型链继承的一个主要问题就是包含引用类型值的原型属性会被所有实例共享。如果一个实例改变了该属性,那么其他实例的该属性也会被改变。
//定义父类构造函数
function Father(){
this.arr = [1, 2, 3];
}
//定义子类构造函数
function Child(){}
//子类继承父类
Child.prototype = new Father();
//实例化
var child1 = new Child();
var child2 = new Child();
//只修改child1的arr属性,发现child2也被改变了
child1.arr.push(4);
console.log(child1.arr);//[1, 2, 3, 4]
console.log(child2.arr);//[1, 2, 3, 4]
2.7.2 构造函数继承
为了解决原型链继承的问题,使用构造函数继承。
通过使用call或apply方法,我们可以在子类中执行父类型构造函数,从而实现继承。
function Parent(){
this.sayHello = function(){
console.log("Hello");
}
}
Parent.prototype.a = "我是父类prototype上的属性";
function Child(){
Parent.call(this);
}
var child1 = new Child();
var child2 = new Child();
var parentObj = new Parent();
console.log(parentObj.a);//"我是父类prototype上的属性"
console.log(child1.a);//undefined
console.log(child1.sayHello === child2.sayHello);//false
例子中child1所继承的sayHello和child2所继承的sayHello,虽然来自同一个父类,但是两个方法是独立的,因此单独修改child1的sayHello不会对child2造成影响。
缺点:它不能继承父类prototype上的属性,每次new一个实例就会执行一次父类构造函数。
2.7.3 组合继承(原型链继承+构造函数继承)
function Parent(){
this.sayHello = function(){
console.log("Hello");
}
}
Parent.prototype.a = "我是父类prototype上的属性";
function Child(){
Parent.call(this);
}
Child.prototype = new Parent();
var child1 = new Child();
var child2 = new Child();
var parentObj = new Parent();
console.log(parentObj.a);//"我是父类prototype上的属性"
console.log(child1.a);//"我是父类prototype上的属性"
console.log(child1.sayHello === child2.sayHello);//false
缺点:调用了两次Parent()
标签:function,console,log,对象,JavaScript,基础,语法,var,name From: https://www.cnblogs.com/fhrq/p/18342172