diff --git a/03-JavaScript基础/07-对象简介.md b/03-JavaScript基础/07-对象简介.md index ac53078..bf28564 100644 --- a/03-JavaScript基础/07-对象简介.md +++ b/03-JavaScript基础/07-对象简介.md @@ -1,4 +1,16 @@ + +## 面向对象简介 + +**对象的作用是:封装信息**。比如Student类里可以封装学生的姓名、年龄、成绩等。 + +对象具有**特征**(属性)和**行为**(方法)。 + +面向对象:可以创建自定义的类型、很好的支持继承和多态。 + +面向对象的特征:封装、继承、多态。 + + ## 对象简介 ### 基本数据类型和引用数据类型的对比 @@ -109,9 +121,50 @@ } ``` +**补充1**:对象的属性值可以是任何的数据类型,也可以是个**函数**:(也称之为方法) + +```javascript + var obj = new Object(); + obj.sayName = function () { + console.log('smyhvae'); + }; + + console.log(obj.sayName); //没加括号,获取的是对象 + console.log('-----------'); + console.log(obj.sayName()); //加了括号,执行函数内容,并执行函数体的内容 + +``` + +打印结果: + +![](http://img.smyhvae.com/20180314_2109.png) + +**补充2**:js中的属性值,也可以是一个**对象**。 + +举例: + +```javascript + var obj = new Object(); + obj.test = true; + obj.test = null; + obj.test = undefined; + + //创建一个对象 + var obj2 = new Object(); + obj2.name = "smyhvae"; + + //将对象 obj2 设置为 obj 的属性 + obj.test = obj2; + + console.log(obj.test.name); +``` + +打印结果为:smyhvae ### 获取对象中的属性 +**方式1**: + 语法: ```javascript @@ -122,7 +175,6 @@ 举例: - ```javascript var obj = new Object(); @@ -141,6 +193,30 @@ ``` +**方式2**:可以使用`[]`这种形式去操作属性 + +对象的属性名不强制要求遵守标识符的规范,但是我们使用是还是尽量按照标识符的规范去做。 + +但如果要使用特殊的属性名,就不能采用`.`的方式来操作对象的属性。比如说,`123`这种属性名,如果我们直接写成`obj.123 = 789`,是会报错的。那怎么办呢?办法如下: + +语法格式如下:(读取时,也是采用这种方式) + +``` +对象["属性名"] = 属性值 + +``` + + +上面这种语法格式,举例如下: + +```javascript + obj["123"] = 789; +``` + + +**重要**:使用`[]`这种形式去操作属性,更加的灵活,因为,我们可以在`[]`中直接传递一个**变量**,这样变量值是多少就会读取那个属性。 + + ### 修改对象的属性值 语法: @@ -164,59 +240,6 @@ ``` - -## 对象的属性名和属性值的补充 - - -### 属性名:可以使用`[]`这种形式去操作属性 - -对象的属性名不强制要求遵守标识符的规范,但是我们使用是还是尽量按照标识符的规范去做。 - -但如果要使用特殊的属性名,就不能采用`.`的方式来操作对象的属性。比如说,`123`这种属性名,如果我们直接写成`obj.123 = 789`,是会报错的。那怎么办呢?办法如下: - -需要使用另一种方式。语法格式如下:(读取时,也是采用这种方式) - -``` -对象["属性名"] = 属性值 - -``` - - -上面这种语法格式,举例如下: - -```javascript - obj["123"] = 789; -``` - - -**重要**:使用`[]`这种形式去操作属性,更加的灵活,因为,我们可以在`[]`中直接传递一个**变量**,这样变量值是多少就会读取那个属性。 - - -### 属性值:js中的属性值,可以是一个对象 - -JS对象的属性值,可以是任意的数据类型,甚至也**可以是一个对象**。 - -举例: - -```javascript - var obj = new Object(); - obj.test = true; - obj.test = null; - obj.test = undefined; - - //创建一个对象 - var obj2 = new Object(); - obj2.name = "smyhvae"; - - //将obj2设置为obj的属性 - obj.test = obj2; - - console.log(obj.test.name); -``` - -打印结果为:smyhvae - - ### in 运算符 通过该运算符可以检查一个对象中是否含有指定的属性。如果有则返回true,没有则返回false。 @@ -281,6 +304,56 @@ JS对象的属性值,可以是任意的数据类型,甚至也**可以是一 属性名和属性值是一组一组的键值对结构,键和值之间使用`:`连接,多个值对之间使用`,`隔开。如果一个属性之后没有其他的属性了,就不要写`,`,因为它是对象的最后一个属性。 +## 遍历对象中的属性:for in + +语法: + +```javascript + for (var 变量 in 对象) { + + } +``` + +解释:对象中有几个属性,循环体就会执行几次。每次执行时,会将对象中的**每个属性的 属性名 赋值给变量**。 + +举例: + + +```html + + + + + + + + + + + + + + +``` + +打印结果: + +![](http://img.smyhvae.com/20180314_2125.png) + + ## 我的公众号 想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 @@ -290,10 +363,3 @@ JS对象的属性值,可以是任意的数据类型,甚至也**可以是一 ![](http://img.smyhvae.com/2016040102.jpg) - - - - - - - diff --git a/03-JavaScript基础/10-作用域.md b/03-JavaScript基础/10-作用域.md index c0bd316..adda68a 100644 --- a/03-JavaScript基础/10-作用域.md +++ b/03-JavaScript基础/10-作用域.md @@ -1,26 +1,149 @@ +> 作用域、变量提升的知识点,面试时会经常遇到。 + +## 作用域(Scope)的概念 + +作用域指一个变量的作用范围。在js中,一共有两种作用域: + +- 全局作用域 + +- 函数作用域 + +## 全局作用域 + +直接编写在script标签中的JS代码,都在全局作用域。 + +- 全局作用域在页面打开时创建,在页面关闭时销毁。 + +- 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用。 + +在全局作用域中: + +- 创建的**变量**都会作为window对象的属性保存。 + +- 创建的**函数**都会作为window对象的方法保存。 + +全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到。 + +### 变量的声明提前(变量提升) + +使用var关键字声明的变量( 比如 `var a = 1`),**会在所有的代码执行之前被声明**(但是不会赋值),但是如果声明变量时不是用var关键字(比如直接写`a = 1`),则变量不会被声明提前。 + +举例1: + +```javascript + console.log(a); + var a = 123; +``` + + +打印结果:undefined。(说明变量 a 被 被提前声明了,只是尚未被赋值) + +举例2: + +```javascript + console.log(a); + a = 123; //此时a相当于window.a +``` + +程序会报错: + +![](http://img.smyhvae.com/20180314_2136.png) + +### 函数的声明提前 + +**函数声明**: + +使用`函数声明`的形式创建的函数`function foo(){}`,**会被声明提前**。 + +也就是说,整个函数会在所有的代码执行之前就被**创建完成**,所以我们可以在函数声明之前,调用函数。 + +代码举例: + +```javascript + fn1(); // 虽然 函数 fn1 的定义是在后面,但是因为被提前声明了, 所以此处可以调用函数 + + function fn1() { + console.log('我是函数 fn1'); + } + +``` + +**函数表达式**: + +使用`函数表达式`创建的函数`var foo = function(){}`,**不会被声明提前**,所以不能在声明前调用。 + +很好理解,因为此时foo被声明了,且为undefined,并没有把 `function(){}` 赋值给 foo。 + +所以说,下面的例子,会报错: + +![](http://img.smyhvae.com/20180314_2145.png) + +## 函数作用域 + +**调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁。** + +每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的。 + +在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量。 + +**作用域的上下级关系:** + +当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(**就近原则**)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错ReferenceError。 + +在函数中要访问全局变量可以使用window对象。(比如说,全局作用域和函数作用域都定义了变量a,如果想访问全局变量,可以使用`window.a`) + +**提醒1:** + +在函数作用域也有声明提前的特性: + +- 使用var关键字声明的变量,会在函数中所有的代码执行之前被声明 + +- 函数声明也会在函数中所有的代码执行之前执行 + + +因此,在函数中,没有var声明的变量都是**全局变量**,而且并不会提前声明。 + +举例1: + +```javascript + var a = 1; + + function foo() { + console.log(a); + a = 2; // 此处的a相当于window.a + } + + foo(); + console.log(a); //打印结果是2 + +``` + +上方代码中,foo()的打印结果是`1`。如果去掉第一行代码,打印结果是`Uncaught ReferenceError: a is not defined` + + +**提醒2:**定义形参就相当于在函数作用域中声明了变量。 + +```javascript + function fun6(e) { // 这个函数中,因为有了形参 e,此时就相当于在函数内部的第一行代码里,写了 var e; + console.log(e); + } + + fun6(); //打印结果为 undefined + fun6(123);//打印结果为123 +``` + + - - - - - - - - - - - - - - - - - - - +## 我的公众号 + +想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](http://img.smyhvae.com/2016040102.jpg) diff --git a/03-JavaScript基础/11-this.md b/03-JavaScript基础/11-this.md new file mode 100644 index 0000000..7bf6507 --- /dev/null +++ b/03-JavaScript基础/11-this.md @@ -0,0 +1,94 @@ + + +## this + +解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的 上下文对象。 + +根据函数的调用方式的不同,this会指向不同的对象:【重要】 + +- 1.以函数的形式调用时,this永远都是window。比如`fun();`相当于`window.fun();` + +- 2.以方法的形式调用时,this是调用方法的那个对象 + +- 3.以构造函数的形式调用时,this是新创建的那个对象 + +- 4.使用call和apply调用时,this是指定的那个对象 + +针对第1和第2条的举例: + +```javascript + function fun() { + console.log(this.name); + } + + + var obj1 = { + name: "smyh", + sayName: fun + }; + + var obj2 = { + name: "vae", + sayName: fun + }; + + var name = "全局的name属性"; + //obj.sayName(); + + //以函数形式调用,this是window + //fun(); //可以理解成 window.fun() + + //以方法的形式调用,this是调用方法的对象 + obj2.sayName(); + +``` + +打印结果:`vae`。 + +**箭头函数中this的指向**: + +ES6中的箭头函数并不会使用上面四条标准的绑定规则,而是会继承外层函数调用的this绑定(无论this绑定到什么)。 + +## arguments(待定) + +在调用函数时,浏览器每次都会传递进两个隐含的参数: + +- 1.函数的上下文对象 this + +- 2.**封装实参的对象** arguments + +例如: + +```javascript + function foo() { + console.log(arguments); + console.log(typeof arguments); + } + + foo(); +``` + + +![](http://img.smyhvae.com/20180315_0903.png) + +arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度。 + +在调用函数时,我们所传递的实参都会在arguments中保存。 + +arguments.length可以用来获取**实参的长度**。 + +我们即使不定义形参,也可以通过arguments来使用实参(只不过比较麻烦):arguments[0] 表示第一个实参、arguments[1] 表示第二个实参... + + +arguments里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象。 + +```javascript + function fun() { + + console.log(arguments.callee == fun); //打印结果为true + } + + fun("hello"); +``` + + diff --git a/03-JavaScript基础/17-对象、作用域和this.md b/03-JavaScript基础/17-对象、作用域和this.md deleted file mode 100644 index 20092a0..0000000 --- a/03-JavaScript基础/17-对象、作用域和this.md +++ /dev/null @@ -1,320 +0,0 @@ - -## 面向对象的概念 - -**对象的作用是:封装信息**。比如Student类里可以封装学生的姓名、年龄、成绩等。 - -对象具有**特征**(属性)和**行为**(方法)。 - -面向对象:可以创建自定义的类型、很好的支持继承和多态。 - -面向对象的特征:封装、继承、多态。 - -## 向对象中添加属性/添加方法 - -首先创建一个对象: - - -```javascript - var obj = new Object(); -``` - -向对象中添加属性: - -```javascript - obj.name = "孙悟空"; - obj.age = 18; -``` - -对象的属性值可以是任何的数据类型,也可以是个**函数**: - -```javascript - var obj = new Object(); - obj.sayName = function () { - console.log('smyhvae'); - }; - - console.log(obj.sayName); //没加括号,获取的是对象 - console.log('-----------'); - console.log(obj.sayName()); //加了括号,执行函数内容,并执行函数体的内容 - -``` - -打印结果: - -![](http://img.smyhvae.com/20180314_2109.png) - -**函数和方法的区别:** - -如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象的**方法**。调用这个函数就说调用对象的方法(method)。但是它只是名称上的区别,没有其他的区别。 - - -```javascript - //调方法 - obj.sayName(); - - //调函数 - fun(); -``` - -## 枚举对象中的属性:for in - -语法: - -```javascript - for (var 变量 in 对象) { - - } -``` - -解释:对象中有几个属性,循环体就会执行几次。每次执行时,会将对象中的**每个属性的名字赋值给变量**。 - - -举例: - - -```html - - - - - - - - - - - - - - -``` - -打印结果: - -![](http://img.smyhvae.com/20180314_2125.png) - -## 作用域 Scope【重要】 - -作用域指一个变量的作用的范围。在JS中一共有两种作用域: - -- 全局作用域 - -- 函数作用域 - -### 全局作用域 - -直接编写在script标签中的JS代码,都在全局作用域。 - -- 全局作用域在页面打开时创建,在页面关闭时销毁。 - -- 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用。 - -在全局作用域中: - -- 创建的变量都会作为window对象的属性保存。 - -- 创建的函数都会作为window对象的方法保存。 - -全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到。 - -**变量的声明提前:** - - -使用var关键字声明的变量( 比如 `var a = 1`),**会在所有的代码执行之前被声明**(但是不会赋值),但是如果声明变量时不是用var关键字(比如直接写`a = 1`),则变量不会被声明提前。 - -举例1: - -```javascript - console.log(a); - var a = 123; -``` - - -打印结果:undefined - -举例2: - -```javascript - console.log(a); - a = 123; //此时a相当于window.a -``` - -程序会报错: - -![](http://img.smyhvae.com/20180314_2136.png) - -**函数的声明提前:** - -- 使用`函数声明`的形式创建的函数`function foo(){}`,**会被声明提前**。 - -也就是说,它会在所有的代码执行之前就被创建,所以我们可以在函数声明之前,调用函数。 - -- 使用`函数表达式`创建的函数`var foo = function(){}`,**不会被声明提前**,所以不能在声明前调用。 - -很好理解,因为此时foo被声明了,且为undefined,并没有给其赋值`function(){}`。 - -所以说,下面的例子,会报错: - -![](http://img.smyhvae.com/20180314_2145.png) - -### 函数作用域 - -**调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁。** - -每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的。 - -在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量。 - -**作用域的上下级关系:** - -当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(**就近原则**)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错ReferenceError。 - -在函数中要访问全局变量可以使用window对象。(比如说,全局作用域和函数作用域都定义了变量a,如果想访问全局变量,可以使用`window.a`) - -**提醒1:** - -在函数作用域也有声明提前的特性: - -- 使用var关键字声明的变量,会在函数中所有的代码执行之前被声明 - -- 函数声明也会在函数中所有的代码执行之前执行 - - -因此,在函数中,没有var声明的变量都会成为**全局变量**,而且并不会提前声明。 - -举例1: - -```javascript - var a = 1; - - function foo() { - console.log(a); - a = 2; // 此处的a相当于window.a - } - - foo(); - console.log(a); //打印结果是2 - -``` - -上方代码中,foo()的打印结果是`1`。如果去掉第一行代码,打印结果是`Uncaught ReferenceError: a is not defined` - - -**提醒2:**定义形参就相当于在函数作用域中声明了变量。 - -``` - - function fun6(e) { - console.log(e); - } - - fun6(); //打印结果为 undefined - fun6(123);//打印结果为123 -``` - - -## this - -解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的 上下文对象。 - -根据函数的调用方式的不同,this会指向不同的对象:【重要】 - -- 1.以函数的形式调用时,this永远都是window。比如`fun();`相当于`window.fun();` - -- 2.以方法的形式调用时,this是调用方法的那个对象 - -- 3.以构造函数的形式调用时,this是新创建的那个对象 - -- 4.使用call和apply调用时,this是指定的那个对象 - -针对第1和第2条的举例: - -```javascript - function fun() { - console.log(this.name); - } - - - var obj1 = { - name: "smyh", - sayName: fun - }; - - var obj2 = { - name: "vae", - sayName: fun - }; - - var name = "全局的name属性"; - //obj.sayName(); - - //以函数形式调用,this是window - //fun(); //可以理解成 window.fun() - - //以方法的形式调用,this是调用方法的对象 - obj2.sayName(); - -``` - -打印结果:`vae`。 - -**箭头函数中this的指向**: - -ES6中的箭头函数并不会使用上面四条标准的绑定规则,而是会继承外层函数调用的this绑定(无论this绑定到什么)。 - -## arguments(待定) - -在调用函数时,浏览器每次都会传递进两个隐含的参数: - -- 1.函数的上下文对象 this - -- 2.**封装实参的对象** arguments - -例如: - -```javascript - function foo() { - console.log(arguments); - console.log(typeof arguments); - } - - foo(); -``` - - -![](http://img.smyhvae.com/20180315_0903.png) - -arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度。 - -在调用函数时,我们所传递的实参都会在arguments中保存。 - -arguments.length可以用来获取**实参的长度**。 - -我们即使不定义形参,也可以通过arguments来使用实参(只不过比较麻烦):arguments[0] 表示第一个实参、arguments[1] 表示第二个实参... - - -arguments里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象。 - -```javascript - function fun() { - - console.log(arguments.callee == fun); //打印结果为true - } - - fun("hello"); -``` - -