知识储备:
什么是语法糖
1.prototype:
- js中每个对象都有prototype属性;
- 每个构造函数都有个属性叫原型;
- 作用:用来返回对象类型原型的引用,为某个特定的类声明通用的变量或函数【即用来给相同类型的所有对象添加
共享
属性】
2.构造函数/构造器:
在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数
。任何的函数都可以作为构造函数存在。
构造函数用来解决一类具有相同属性和方法的对象的问题。实现代码的复用。
-
构造函数与普通函数之分,主要从功能上进行区别:
1.构造函数的主要功能为初始化对象,特点是和new 一起使用。
2.new就是创建对象,从无到有。构造函数就是为初始化的对象添加属性和方法。
1,【每当创建一个实例对象,就会创建一个新的内存空间。】 2,创建的实例对象都会去访问构造函数。实例对象会拥有构造函数内this.的属性和方法。
3.构造函数定义时首字母大写(规范)。
【拓展:】
对new理解:new 申请内存, 创建对象。当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而非值类型。 -
构造函数的返回值:
1,构造函数无return时默认返回this。this指向实例对象的内存空间。
function Person1() {
this.name = 'zhangsan';
}
var p1 = new Person1(); // p1: { name: 'zhangsan'}
2,构造函数如果返回基本数据类型的话,最后还是默认返回this.
function Person2() {
this.age = 28;
return 50;
}
var p2 = new Person2(); //p2: { age: 28}
console.log(p2.age); // 28
3.返回复杂数据类型值的话,最终返回的是该对象
function Person3() {
this.height = '180';
return ['a', 'b', 'c'];
}
var p3 = new Person3();
console.log(p3.height); // undefined
console.log(p3.length); // 3
console.log(p3[0]); // 'a'
function Person4() {
this.gender = '男';
return { gender: '中性' };
}
var p4 = new Person4();
console.log(p4.gender); // '中性'
3.js的解析和执行过程:
new Foo() 会去调用原型对象;new Foo则是去调用它的私有属性/函数。
js先会去找是否有var let等关键字,分配内存空间;找function,分配内存空间。然后再执行运算操作。最后逐行执行。
4.变量提升,函数提升
预解析/预处理/函数提升的函数必须是function声明的函数,=赋值的函数不存在预处理:
d();//hello
e();//e is not a function
function d(){//用声明的方式声明的函数
console.log('hello');
}
var e = function(){//函数表达式
console.log('world');
}
5.js运算符优先级
【new Foo() > . > new Foo】
优先级 | 运算类型 | 关联性 | 运算符 |
---|---|---|---|
( ) | |||
. | |||
… [ ] | |||
new …( ) | |||
… ( ) | |||
?. | |||
new … | |||
… ++ | |||
… - - | |||
! … | |||
~ … | |||
+ … | |||
_ … | |||
++ … | |||
- - … | |||
typeof … | |||
void… | |||
delete … | |||
await … | |||
… * * … | |||
… * … | |||
… / … |
经典面试题来啦~~~~~~~~~
// function a() { };
// a.get = function() {
// console.log('555');
// }
// a.get();
// function Foo1() {
// this.haha = function () {//在Foo函数中声明的getName函数没有加var/let关键字,默认全局作用域。
// console.log('a');
// };
// this.value='999';
// return this;
// };
// new Foo1.haha();//创建实例对象,访问构造函数,访问构造函数的方法haha() haha必须加括号
function Foo() {
getName = function () {//在Foo函数中声明的getName函数没有加var/let关键字,默认全局作用域。对全局函数getName的重新赋值
console.log(1);
};
return this;
};
Foo.getName = function () {//Foo函数中的属性getName()
console.log(2);
};
// Foo.prototype=new Foo1(); 把Foo1的所有属性方法都继承给Foo
Foo.prototype.getName = function () { //Foo函数的原型方法
console.log(3);
};
var getName = function () { //对全局函数重新赋值
console.log(4);
};
function getName() {//全局函数getName的创建
console.log(5);
};
// window对象表示浏览器打开的窗口。js的函数,全局对象和变量都会自动成为window对象内的成员
// console.log(Foo);//输出是整个函数体Foo
// console.log(Foo());//输出是window对象,==this 【如果Foo()函数没有return this,输出是undefined】
// console.log(new Foo());//Foo {} [new Foo()的操作等同于new Foo,都是创建一个实例对象]
getName();//4 getName()是全局函数的引用---4会把5覆盖
Foo.getName();//2
Foo().getName();//1 this.getName()
getName();//1 全局函数getName()
new Foo.getName();//2 ==>new (Foo.getName())
new Foo().getName();//3 ==>(new Foo()).getName() new Foo()得到一个实例对象,调用构造函数Foo(),调用Foo的原型方法
new new Foo().getName();//3 ===> new (new Foo().getName())
console.log(new Foo().getName());//undefined
console.log(new Foo.getName());//Foo.getName(){}