JS基础概念整理与简单练习-Part2
对象(Object)-相关知识点1:
- 对象的属性名不强制要求遵守标识符的规范,但尽量按规范书写;
- 如果要使用特殊的变量名,不能采用 . 的方式来操作,而是要写成:
语法: 对象["任意属性名"] = 任意属性值
- 读取时也需要采用[ ]的形式
- 可在[ ]中直接传递一个变量
- in-运算符:检查对象中是否含有指定的属性
语法: "属性名" in 对象
- JS中的变量都是保存到栈内存中的,基本数据类型的值直接在栈内存中存储,值与值之间是独立存在的。
- 引用数据类型是保存在堆内存中的,每创建一个新对象,就会在堆内存中开辟出一个新空间,而变量保存的是对象的内存地址(对象的引用)。如果两个变量保存的是同一个对象引用,当其中一个通过变量修改属性时,另一个也会改变。
- 其中一个设为null(空对象指针),另一个不影响。
- 当比较两个基本数据类型时,就是比较值;而比较两个引用数据类型时,是比较两个对象的内存地址。
- 使用对象字面量创建对象,属性名可加引号可不加(特殊名字就加,不是就不用)。
var obj = {}; 语法:{ 属性名:属性值, 属性名:属性值, ……}
- 属性后没有其他属性就不用再写,(逗号)了。
- 枚举对象中的属性
语法: for(var 变量 in 对象){ } // 演示: for(var n in 对象){ // n为属性名 console.log(n); // 取变量还是得靠[] console.log(obj[n]); }
函数(Function)-相关知识点:
- 使用typeof检查一个函数对象时,会返回Fuction。
- 因为函数属于对象,因此可以用构造函数创建函数
// 可以将要封装的代码以字符串的形式传给构造函数。 var fun = new Fuction("console.log('Hello!')") // 建议不要这么用 fun( );
- 使用函数声明来创建函数。
function functionName(arg0,arg1){ }
- 使用函数表达式创建函数。
var functionName = function(arg0,arg1){ }; //将匿名函数赋值给变量,最好写上; 分号 functionName = function(arg0,arg1){ } //匿名函数
- 调用函数时解析器不会检查实参的类型,所以要注意是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查。
- 调用函数时,解析器也不会检查实参的数量,多余实参不会被赋值;如果实参数量少于形参数量,则没有对应实参的形参为undefined。
- 如果return语句后不跟任何值/不写 就相当于返回一个undefined。(alert就没有返回值)
- 分析如下代码:
function fun1(arg){return results;} function fun2(a){console.log(a);} // fun2(fun1()); // 传入调用函数,把fun1的返回值传给a fun2(fun1); //传入函数对象本身, 把fun1对象传给a
- 立即执行函数:函数定义完立即被调用,这种往往只能执行一次。
(function(形参){ 代码块 })(实参); //红括号用来表示该匿名函数为一个整体,绿括号表示调用前面的匿名函数
作用域(Context)-相关知识点:
- 全局作用域:直接写在script标签中的JS代码,全在全局作用域。
- 全局作用域在页面打开时创建,在页面关闭时销毁。
- 在全局作用域中有一个全局对象window,它由浏览器创建,可以直接使用。
- 在全局作用域中,创建的 变量/函数 都会作为window对象的 属性/方法 保存。
var a = 10; console.log(window.a); // 10
- 变量的声明提前:使用var关键字声明的变量,会在所有的代码执行之前被声明(不会被赋值)。
- 如果声明变量时不使用var关键字,则变量不会被提前声明。
- 函数的声明提前:使用函数声明形式创建的函数,会在所有的代码执行之前被创建,所以可以在函数声明前调用函数。
- 使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用
fun1(); //可 fun2(); //报错 function fun1(){代码} //提前创建fun1 var fun2 = function(){ 代码 }; //只提前声明了fun2变量,没有进行赋值
- 全局作用域中的变量都是全局变量,在页面中的任意部分均可被访问到。
- 函数作用域:调用函数时创建的函数作用域,函数执行完毕后,函数作用域销毁。
- 每调一次函数就会创建一个新的函数作用域,他们之间是相互独立的。
- 在函数作用域中可以访问到全局作用域的变量;全局作用域中无法访问到函数作用域的变量。
- 在函数作用域中寻找一个变量:先在自身作用域找,没有就在上一级作用域找,直到找到全局作用域,再没有就报错ReferenceError。
- 在函数中访问全局变量可以window.变量。
- 在函数作用域中也会声明提前,在函数中所有代码执行之前被声明。
- 在函数中,没有var声明的变量会变成全局变量
function fun(){ //相当于这里有个var a; console.log(a); var a = 10; } fun(); // "undefined"
var c = 33; function fun2(){ console.log(c); var c = 10; } fun2(); //"undefined"
var c = 33; function fun2(){ console.log(c); c = 10; } fun2(); //33
var c = 33; function fun2(){ c = 10; } console.log(c); fun2(); //10
- 定义形参就相当于在函数中声明了变量
this对象-相关知识点
- 解析器/浏览器在调用函数时,每次都会向函数内部传递进隐含的参数this。
- this指向一个对象,这个对象称为函数执行的上下文对象。
- 根据函数的调用方式不同,this会指向不同的对象。① 以函数形式调用时,this永远是window;② 以方法的形式调用时,this就是调用方法的那个对象;③ 当函数为构造函数时,this为新建的对象;④ 使用call和apply调用时,this是指定的对象。
对象(Object)-相关知识点2:
- 使用工厂方法创建对象(用的不多)
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name) }; return o; } var person1 = createPerson(...);
- 使用工厂方法创建的对象(缺点),使用的构造函数都是Object。所以创建的对象都是Object类型,导致无法区分出不同类型的对象。 //不管是啥都得new Object
- 使用构造函数模式创建对象,构造函数的创建方法与普通函数无区别,不同的是构造函数习惯上首字母大写。
function Person(name, age, job){ this.name = name; ... } var person1 = new Person(...);
- 构造函数与普通函数的区别在于调用方式不同:
- 普通函数直接调用,例如person( );
- 构造函数需要使用new关键字来调用,即new Person( );
- 构造函数的流程:
- 看到new:立刻创建一个新对象;
- 将新建的对象设置为函数中的this,在构造函数中,可以使用this来引用新建的对象;
- 逐行执行函数中的代码;
- 将新建的对象作为返回值返回。
- 使用同一个构造函数创建的对象,称为一类对象。也将一个构造函数称为一个类。
- 我们通过一个构造函数创建的对象,称为该类/构造函数的实例。
- 使用 instanceof 可以检查一个对象是否是一个类的实例。
- 构造函数(缺点)每执行一次就会创建一个新的sayName方法,每个实例的方法都是唯一的(不相等)。
原型模式(prototype)
- 创建的每一个函数,解析器都会向函数中添加一个属性prototype。这个属性对应着一个对象,这个对象就是所谓的原型对象。
- 如果函数作为普通函数调用prototype没有任何作用。
- 当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__来访问该属性。
function MyClass(){ } var mc = new MyClass(); console.log(mc.__proto__ == MyClass.prototype) // "true"
- 原型对象就相当于一个公共区域,所有同类的实例都可以访问到这个原型对象。因此可以将对象中共有的内容,统一设置到原型对象中。
function MyClass(){ } MyClass.prototype.a = 123; var mc1 = new MyClass(); var mc2 = new MyClass(); mc1.a = 'hello' console.log(mc1.a)
- 当访问对象的一个属性或方法时,会先在自身寻找,有则直接使用,没有则到原型对象中寻找。
- (优点)既保证函数不会被重复创建,又不会污染全局定义域。
- 以后在创建构造函数时,可以将对象共有的属性和方法,统一添加到构造函数的原型对象中。
- 使用in检查对象中是否含有某个属性时,如果对象中没有但原型里有,也会返回true。可以使用对象的hasOwnProperty( )检查对象自身是否有该属性。
- 原型对象也是对象,也有原型。当我们使用一个对象的属性或方法时,会先在自身中寻找,没有则向上再找,直到找到Object对象的原型。
- Object对象的原型没有原型,再找不到就undefined。//且 Object.__proto__ 会返回"null"
toString-相关知识点:
- 当我们直接在页面中打印一个对象时,实际上是输出对象的toString( )方法的返回值。//现在好像不是了,直接输出Object结果
- 如果希望在输出对象时不输出[object object],可以为对象添加一个toString( )方法。
垃圾收集-相关知识点:
- 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象。此时这个对象就是一个垃圾。
- 在JS中拥有自动垃圾回收机制,会自动将垃圾对象从内存中销毁,不需要也不能进行垃圾回收操作。
- 需要将不用的对象设为null。
数组练习2
正则表达式练习