JS进阶知识。
文章目录
目录
前言
这是函数的高级知识,主要涉及到JS原型链问题、执行上下文问题、作用域问题以及函数的闭包问题,是面试最常问到的JS考察点。
一、原型与原型链。
1.1 什么是原型(prototype)?
<title></title>
</head>
<!--
1、函数的prototype属性 ↑
*每个函数都有一个Prototype属性 它默认指向一个object 空对象(即为原型对象)_
*原型对象中有一个属性 constructor 它默认指向函数对象
2、给原型对象添加属性(一般都是作为方法添加)
*作用:所有的函数对象的实例对象自动拥有原型中的属性与方法;
-->
<body>
<script type="text/javascript">
console.log(Date.prototype)
function Fun1(){
}
console.log(Fun1.prototype)//默认指向一个object空对象 没有属性
console.log('________________________________')
//原型对象中有一个属性 constructor 它默认指向函数对象
console.log(Date.prototype.constructor === Date)
console.log(Fun1.prototype.constructor === Fun1)
//函数对象的实例对象自动拥有原型中的属性与方法;
Fun1.prototype.test = function (){
console.log('test()')
}
var fun1 = new Fun1();
fun1.test();
</script>
便于理解 关系如下图所示
其实为了理解原型链 我们首先得了解并承认下列最基础的结论:
我们继续。
1.2 什么是显式原型与隐式原型?
<title></title>
<!--
1.每个函数function 都有个prototype ,即为 显式原型(属性)
2、每个实例对象都有一个__proto__, 即为 隐式原型(属性)
3、对象的隐式原型的值 等于 其构造函数的显式原型的值。
***我们通过显式原型添加方法! 我们能直接通过显式原型直接操作它。
但是我们不能直接操作隐式原型!!(ES6之前 -我们正在学习ES5);
-->
</head>
<body>
<script type="text/javascript">
function Fn(){//故创建函数对象的内部语句就是 this.prototype = {}
}
//1、每个函数function 都有一个prototype 显式原型
console.log(Fn.prototype)
//2、每个实例对象都有一个__proto__, 即为 隐式原型(属性)
var fun1 = new Fn ()//由后面往前推我们可以知道————
//创建实例就是 this._proto__ = Fn.prototype 将原型函数的显示原型地址值赋值给了实例对象的隐式原型。
console.log(fun1.__proto__)
//3、对象的隐式原型的值 等于 其构造函数的显式原型的值。
console.log(Fn.prototype === fun1.__proto__)//返回一个true;
//两个都是引用类型的 变量保存的是 !地址值! 两个保存一样的地址 指向同一块 →原型对象;
</script>
! 注意 在Chrome等多数浏览器中 在控制台查看对象属性时 __proto__ 一般以[[prototype]]存在。
1.3 原型链:
<title></title>
<!--
-->
</head>
<body>
<script type="text/javascript">
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的__proto__是FN.prototype 而后者的__proto__是 Object.prototype. 而再后者的__proto__找不到 返回undefined
/*原型链————在访问一个对象的属性时 现在自身的属性中查找 没找到再去__proto__链上往原型对象里找
如果最终找不到了 返回undefined(现在返回Null))别名*隐式原型链 作用 查找对象的属性与方法。
构造函数 与 原型 与实体对象的关系图解!
*/
console.log('______________________________________________')
console.log(Object.prototype.__proto__)
/*原型链补充总结:
1*函数的显式原型指向的对象默认是空的Object实例对象(但是Object不满足 它的显式原型对象是)
*/
console.log(Fn.prototype instanceof Object) //true
console.log(Object.prototype instanceof Object)//false 唯一例外
console.log(Function.prototype instanceof Object)//true
console.log('————————————————————————————————————————————————————————————————')
/* 2 Function 是它自身的实例。。 所有函数都是Function 的实例对象。
它是实例对象 有隐式原型↓ ↓ 它是自身的实例 有显式原型属性 */
console.log(Function.__proto__ === Function.prototype)//输出true
//Object的原型对象是原型链尽头
console.log(Object.prototype.__proto__ === null)//找不到它的原型了
</script>
更直观地 我们可以画出下列图 所有的原型链关系基本都可以在下图中找到对应关系:
1.4 原型链属性问题:
<title></title>
</head>
<body>
<script type="text/javascript">
function Pers(){
}
Pers.prototype.name = 'mqy'
var per1 = new Pers()
console.log(per1.name,per1)//**这里来到Pers.prototype找到属性name并输出
var per2 = new Pers()
per2.name = 'yyy'//这里是为 per2函数添加了name属性 值为yyy
console.log(per1.name)//仍然是‘mqy’没变 因为在自身per1里没有这个属性 就去原型链中找
console.log(per2.name)//改变为'yyy'了; 因为在per2中已经找到了这个属性 不去原型链中找了。
//总结:读取对象属性值时,会自动去原型链中查找,而再设置对象属性值时,不查找原型链 如果当前对象没有此属性 直接添加此属性
console.log('——————————————再来看看属性—