目录
- var c={name:'tom'};
- console.log(c);
- var a={age:12};
- var b=a;
- a={name:'bob',age:13};
- b.age=14;
- console.log(b.age,a.name,a.age);
如何表述a和b的关系?
- var obj={age:18};
- function set(obj){
- obj={age:12};
- }
- set(obj);
- console.log(obj.age);
(易错)函数执行完,内部内容会被垃圾回收(对)
如何理解obj的内容输出没有发生改变呢?——>obj在加入函数后,堆地址改变了,但是他并没有改变之前obj里存的内容
- var a=3;
- var obj={};
- var obj2=null;
区分“释放”和“垃圾回收”
- var propName='myAge';
- var value=18;
- p[propName]=value;
- console.log(p[propName]);
如何理解变量名不确定的情况?
对象中的[]可以理解为函数的传参,所以他可以是个字符串也可以是一个变量,因此该案例中的p[propName]等价于p.myAge
什么是函数?
为什么要用函数?
如何定义函数?
如何调用(执行)函数?
- /*
- 编写程序实现以下功能
- */
- function showInfo(age) {
- if (age < 18) {
- console.log("未成年,再等等!");
- } else if (age > 60) {
- console.log("算了吧~~~");
- } else {
- console.log("刚好");
- }
- }
-
- showInfo(16);
- showInfo(20);
- showInfo(65);
-
- function f1(){
- console.log('f1');
- }
- var f2=function(){
- console.log('f2');
- }
- f1();
- f2();
-
-
- var obj={};
- function test2(obj) {
- this.xxx='atguigu';
-
- }
- test2.call(obj);
- console.log(obj.xxx);
-
什么是回调函数?
常见的回调函数
函数分为两种,一种用于储存,一种用于执行
全称:Immediately-Invoked Function Expression
作用
- // 匿名函数自调用
- (function(){
- console.log('......')
- var a=3
- console.log(a+3);
- })()
- var a=4
- console.log(a);
-
- (function(){
- var a=1;
- function test(){
- console.log(++a)
- }
- window.$=function(){
- return {
- test:test
- }
- }
- })()
- $().test();
-
注意:
- window.$:把window对象传入这个匿名函数中,并且同时执行这个函数,在页面载入之前就执行
- $是一个函数
- $执行后返回的是一个对象
this是什么?
如何确定this的值?
在以下2种情况下不加分号会有问题
- var a=3
- ;(function(){
-
- })()
错误理解:
var a=3(function(){})();
3是undefined,无法运行
- var b=4
- ;[1,3].forEach(function(){
-
- })
错误理解:
- var b=4[3].forEach(function(){
- })
1.函数的prototype属性
每个函数都有一个prototype属性,他默认指向一个object空对象(即:原型对象)
原型对象中有一个属性constructor,它指向函数对象
2.给原型对象添加属性(一般都是方法)——>用于实例对象
作用:函数的所有实例对象自动拥有原型中的属性(方法)
上图,表明对象能找到对象原型,对象原型能找到对象,两者是相互的
- console.log(Date.prototype,typeof Date.prototype);
- // {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
- // object
- function Fun(){
-
- }
- Fun.prototype.test=function(){
- console.log('test()');
- }
- console.log(Fun.prototype);//默认指向一个空对象(没有我们的属性)
- // {test: ƒ, constructor: ƒ}
- // 当我们特地加上才会有我们的属性
-
- // 原型对象中有constructor,他指向函数对象
- console.log(Date.prototype.constructor===Date);//true
- console.log(Fun.prototype.constructor===Fun);//true
-
每个函数function都有一个prototype,即显式原型(属性)
每个实例对象都有一个__proto__,可以称为隐式原型(属性)
对象的隐式原型的值为其对应的显式原型的值
- function FN(){
-
- }
- console.log(FN.prototype);
- var fn=new FN();
- console.log(fn.__proto__);
- console.log(FN.prototype===fn.__proto__);
-
- FN.prototype.test=function(){
- console.log('test()');
-
- }
- fn.test();
内存结构图(下方)
总结:
函数的prototype属性:在定义函数时自动添加的,默认值是一个空Object对象
对象的__proto__属性:创建对象时自动添加的,默认值为构造函数的prototype属性值
程序员能直接操作显式原型,但不能直接操作隐式原型(ES6之前)
访问一个对象的属性时
别名:隐式原型链
作用:查找对象的属性,不是查找对象的变量
- function FN(){
- this.test1=function(){
- console.log("test1()");
- }
-
- }
- FN.prototype.test2=function(){
- console.log("test2()");
- }
- var FN=new FN()
- fn.test1()
- fn.test2()
- console.log(fn.toString);
- fn.test3()
- var o1=new Object();
- var o2={};
图解:
补充:
函数的显式原型指向的对象默认是空Object实例对象(但Object不满足)
- console.log(FN.prototype instanceof Object);//true
- console.log(Object.prototype instanceof Object);//false
- console.log(Function instanceof Object);//true
所有函数都是Function的实例(包括Function)
console.log(Function.__proto__===Function.prototype);//true
Object的原型对象是原型链尽头
console.log(Object.prototype.__proto__);//null
- function Fn(){
-
- }
- Fn.prototype.a='xxx';
- var fn1=new Fn()
- console.log(fn1.a,fn1);
-
- var fn2=new Fn()
- fn2.a='yyy'
- console.log(fn1.a);//xxx
- console.log(fn2.a);//yyy
表达式:A instanceof B
(A为实例对象,B为构造函数)就是判断A是否为B的实例
如果B函数的显式原型对象在A对象的原型链上,返回true,否则返回false
Function是通过new自己产生的实例
案例一:
- function Foo(){}
- var f1=new Foo();
- console.log(f1 instanceof Foo);//true
- console.log(f1 instanceof Object);//true
案例二:
- console.log(Object instanceof Function);//true
- console.log(Object instanceof Object);//true
- console.log(Function instanceof Function);//true
- console.log(Function instanceof Object);//true
-
- function Foo(){
- console.log(Object instanceof Foo);//true
- }
- function A(){
-
- }
- A.prototype.n=1
- var b=new A()
- A.prototype={
- n:2,
- m:3
- }
- var c=new A
- console.log(b.n,b.m,c.n,c.m);
- function F(){}
- Object.prototype.a=function(){
- console.log('a()');
- }
- Function.prototype.b=function(){
- console.log('b()');
- }
- var f=new F()
- f.a()//a()
- // f.b()endefined
- F.a()//a()
- F.b()//b()
- console.log(f);
- console.log(Object.prototype);
- console.log(Function.prototype);
引入:为什么输出为undefined?
- var a=3
- function fn(){
- console.log(a);
- var a=4;
- }
- fn()
答:实际运行时,函数体先在内部创建了a,因此在函数中找到的是当前的a,代码如下
- var a=3
- function fn(){
- var a;
- console.log(a);
- a=4;
- }
- fn()
1.变量声明提升
2.函数声明提升
- console.log(b);//undefined
- fn2();//可调用 函数提升
- fn3()//不能 变量提升
-
- var b=3;
- function fn2(){
- console.log('fn2()');
- }
- var fn3=function(){
- console.log('fn3()');
- }
3.问题:两者是如何产生的?
答:如上代码
1.代码分类
2.全局执行上下文
- console.log(a1,window.a1);//undefined undefined
- a2()//a2
- console.log(this);//window
-
- var a1=3
- function a2(){
- console.log('a2');
- }
- console.log(a1);//3
3.函数执行上下文
- function fn(a1){
- console.log(a1);//3
- console.log(a2);//undefined
- a3()
- console.log(this);//window
- console.log(arguments);//伪数组
-
- var a2=3
- function a3(){
- console.log('a3');
- }
- }
- fn(2,3)