一、对象
1.概念:
- 对象是拥有属性和方法的数据
var obj = {
//obj对象的属性
name: "lusis",
age: 21,
tezheng: {
hair: "黑色",
money: 200
},
//obj对象的方法
sayName: function () {
console.log(obj.name, obj["name"])
},
}
obj.sayName()
//注意:属性不能同名,非严格模式下同名不会报错但后者会覆盖前者
- 除了5种基本数据,js里面其他的值都是对象(函数是特殊的对象)
2.创建对象:
(1) 对象直接量:
- 由一个大括号将若干个键值对{属性值:属性名}括起来的组成
- 属性值和属性名之间用 : 隔开
- 每个键值对之间用 , 隔开
eg.
//语法糖
var obj = {
name: "Feo",
age: 21
}
(2) new关键字:
new后面跟一个函数(构造函数)表示创建对象
var obj = new Object();
var f1 = new fn();
二、函数
1.概念:
- 函数是实现功能的代码块
- 写法:3种 定义函数 声明函数 Function内置构造函数
- 调用函数:函数名(); 每调用一次执行一次
- 每次调用函数都会产生一个this 谁调用这个函数 this就指向谁
-
是一种特殊的对象(引用数据) typeof的结果是function 而不是 object
2.函数的写法
声明函数:直接在作用域写一个函数 系统预编译时会创建这个函数对象
必须写函数名(仅一种写法)
function fn(形参) {函数体}
定义函数:是创建函数的语法糖 直接生成一个函数数据(对象) 被标识引用
直接创建一个函数 把它当做一个数据 可以不写名字 (多种写法)
var a=function(){};
Function内置构造函数:标准地创建一个函数对象
通过内置的 JavaScript 函数构造器(Function())定义
var fn=new Function("形参","函数体")
3.函数的调用
- 函数只有在调用时才会执行
- 函数名后面加小括号代表执行函数
- 函数的调用 最后一定会生成一个结果(数据)即返回值
4.函数的返回值
- 函数没有写return返回值的话 调用的结果就是系统返回的undefined
- 写了返回值 就是返回的数据
- return 关键字后面紧跟的是一个表达式
- return 一旦运行了 函数体后面的代码不会执行 直接生成结果
- 不写return或者return紧跟着的后面不写代码 就是一个空表达式 默认返回undefined
- 如果想要在return的第二行写表达式 就在return的后面加()
- return可以写可以不写 但写了后 return后紧跟着(同一排)的一定要有表达式或者小括号()
5.形参和实参
- 形参:在定义函数时使用的参数,用来接收调用函数时传进来的参数
- 实参:是在调用时传递给函数的值,保存在类数组arguments里面 函数内部可用
- 实参的个数可以比形参的个数多 按顺序赋值 多的不会覆盖前面的 不影响程序的执行但会影响性能
- 实参的个数可以比形参的个数少或不传 按顺序赋值 多出的形参为undefined 可能会影响程序的执行逻辑 =>解决方案:设计函数时提前预设(形参变量给默认值)
6.函数的属性
- 函数的length属性 代表的是形参的个数(笔试题)
- 函数的name属性 代表的是函数名
7. 变量的作用域(补充)
- 作用域:变量能使用的范围
- 在ES5中,函数的代码块内部的代码可以访问形参变量 也可以访问外部(全局)的变量 就近优先
- 函数外面的代码不能直接访问函数内部的变量
- 全局变量:会在程序运行时,把它设置为window对象的属性
- 局部变量:在函数内部能使用 外部不能使用 (var 形参)
8.匿名函数
- 用小括号括起一个没有函数名的函数 再加一个小括号调用
(function(){console.log(this)})() //调用的是window对象
function fn() {
return function fm() {
console.log(this)
}
}
fn()() //调用的是window对象
三、this关键字
1.概念:
- 代表执行(调用this所在的函数)这个this代码的环境对象
- 代表了函数调用时的调用者 谁调用的函数,函数里的this就指向谁
- this代表了一个对象 常常在项目中要给一个对象操作成员(添加、修改属性)
2.this 法则:
在js中无论多复杂的程序 this只需要看离它最近(嵌套)的function这个单词的调用者
找this:
- 看this在哪个函数里面:离this这个单词最近(嵌套)的的function/方法 这个单词就是就是那个函数 没有就是window
- 这个函数找到了 是哪个代码让这个找到的函数执行的 直接辨别调用者(调用者和持有者)
3.this规律总结
- 全局作用域里的this: this-->window
- 全局下函数里的this: this-->window
- new 操作调用函数: this-->新创建的对象(实例对象)
- 函数写在对象的属性值里 通过对象属性调用函数:this-->obj
this所在的函数的调用者:
fn()==>window
obj.fn()==>obj对象
obj.xx.say()==>obj.xx取出的对象
obj.fn().say==>obj.fn()调用后返回了一个对象
new fn()==>fn函数运行 里面的this是创建的对象
4.练习
实例1:
//打印结果:obj obj window
var obj = {
name: "jack",
say: function () {
console.log(this) //是obj调用的say()函数 所以打印obj对象
function fn(a) {
console.log(a, this)
//a=this=obj 所以a打印obj
//fn()函数是window调用的 所以this打印window
}
fn(this) //此时this的值为obj传入fn函数
}
}
obj.say()
实例2:
四、new关键字
1.概念
- 后面一般跟一个函数 是创建对象的表达式(运算符) 整个表达式一定会得到一个结果(对象)
2.new的步骤
1.创建一个空对象==>创建一个空对象{} 给它添加一个属性__proto__ 这个属性引用fn.prototype
2.运行构造函数 让内部的this指向创建的对象(用创建的空对象去调用构造函数)
3.整个表达式的结果看函数的返回值
(1)返回值是引用数据 那么就是返回值
(2)返回值不是引用数据 那么就是这个运行完毕之后的创建的那个对象
3.构造函数
- 任何对象都是函数创建出来的 ==> 任何对象都有构造函数
- new fn ==>创建对象 然后调用函数 不传参 ==> new无参
- new fn() ==>创建对象 然后调用函数 并传参 ==> new带参
实例1:
function fn(name, birthday) {
this.name = name
this.birthday = birthday
this.life = 1
this.money = 0
this.makeMoney = function () {
this.money += 1
}
}
var obj = new fn("lusis", "2000-01-01")
//1.{}
//2.{}.fn{}
//3 ==>{name:"lusis",birthday:"2000-01-01",life:1,money:0,makeMoney:func}
// ==>obj={name:"lusis",birthday:"2000-01-01",life:1,money:0,makeMoney:func}
obj.makeMoney()
console.log(obj)
实例2:
function fn() {
var obj = {
say: function () {
return obj
}
}
return obj
}
var re = new fn() //函数返回值为obj re=obj
var re2 = fn().say //函数调用内部对象的属性 得到function函数
var re3 = new re2() //obj
console.log(re) //obj
console.log(re2) //f
console.log(re3) //obj
五、this、new、构造函数程序分析
实例1:
function fn() {
this.name = "karen"
return function fm() {
console.log("fm运行了")
this.name = "jack"
}
}
var f1 = new fn() //函数的返回值为函数(引用数据) f1就是fm()
console.log(f1.name) //fm 函数的名字
var f2 = new(new fn())() // ==>var f2=new fm() 返回值为创建的对象 ==> this.name=f2.name
console.log(name) //window自带的name成员 "" 空字符串
console.log(f2.name) //jack
实例2:
function fn() {
this.name = "marry"
var obj = {
name: "karen",
fm: function () {
this.name = "jack"
}
}
return obj;
}
var f1 = new fn() //返回值为obj f1=obj
console.log(f1.name) //==> obj.name ==> karen
var f2 = new((new fn()).fm)() //(new fn()).fm ==> obj.fm
// ==> fm函数当构造函数 无返回值 f2为创建的对象
console.log(f2.name) //f2.name=this.name=jack
var f3 = new fn() //==> obj.name ==> karen
var f4 = new(f3.fm)() //==> fm函数当构造函数 无返回值 f2为创建的对象
console.log(f3.name, f4.name) // karen jack
实例3:
function Parent() {
this.a = 1;
this.b = [1, 2, this.a]; //this.a是取值操作 不变
this.c = {
demo: 5
};
this.show = function () {
console.log(this.a, this.b, this.c.demo) // 4 [1,2,1] 3
}
this.change = function () {
this.a = this.b.length; //3
this.c.demo = this.a++; //3赋值给this.c.demo后加1 this.a更新为4
}
}
var parent = new Parent();
//即 var parent={a:1,b:[1,2,1],c:{demo:5},show:func,change:func}
parent.change();
//parent={a:4,b:[1,2,1],c:{demo:3},show:func,change:func}
parent.show();