函数数据类型
普通函数、类(内置类/自定义类)、箭头函数 (都是Function的实例)
对象数据类型
普通对象、数组对象、正则对象、日期对象、实例对象、函数对象(函数也是一个对象,也像普通对象一样,有自己的键值对)、类的prototype也是对象 (都是Object的实例)
-
- 每一个函数(除ES6的箭头函数外)都有一个内置的属性prototype(原型属性),属性值是一个对象,在对象中会存储当前类的公共属性和方法
-
- 在prototype的堆内存中,如果是浏览器为其默认开辟的堆内存,会存在一个内置的属性:constructor构造函数,属性值就是当前类本身
-
- 每一个对象都有一个内置属性:proto(原型链属性),属性值是当前实例所对应类的prototype
原型链查找机制
调用当前实例对象的某个属性(成员访问),先看自己私有属性中是否存在,存在调用的就是自己私有的;不存在,则默认按照
__ proto __找所属类prototype上的公有属性和方法;如果还没有,再基于prototype上的__ proto __继续向上级查找,直到找到Object.prototype为止
function Fn() {
this.x = 100;
this.y = 200;
this.getX = function () {
console.log(this.x);
}
}
// 都是把Fn执行了,创造了实例(区别就是运算符优先级)
let f1 = new Fn(); //有参数new 19
let f2 = new Fn; //无参数new 18
// Fn() 函数执行
// Fn 函数本身
内置类的原型上扩展方法:
例题

注意:
-
浏览器默认开辟的堆内存在没有被占用后,会被释放掉。
-
重定向原型指向的时候:之前原型上的内容会丢失,包含
constructor -
原型重定向之后,喂了保证结构的完整性,我们一般要手动设置
constructor属性fun.prototype.constructor = fun
- 内置类的原型上会默认存在很多常用的方法
Array.prototype / String.prototype / Object.prototype ...
这些方法实例都可以调用,但是内置的方法不一定能满足所有的开发需求,有很多方法需要自己来编写
- 向原型上扩展的方法,调用起来比较的方便
调用方法:
实例.方法() =>方法执行的时候,方法中的THIS就是当前处理的实例**
1)扩展的方法名字最好设置前缀,例如:Myxxx,防止自己扩展的方法替换了内置的方法
2)THIS的结果一定是对象数据类型值,所以向基本数据类型的原型上扩展方法,方法被执行的时候,方法中的THIS不再是基本类型,但是还按照原始的方法处理即可(因为在运算的时候,会隐式调用对象的valueOf方法,返回它的原始值,而原始值就是之前的基本数据类型值)
3)如果返回的结果依然是当前类的实例,还可以继续调用当前类原型上其它的方法(如果不是自己类的实例,可以掉用其它类原型上的方法) => “链式写法”
3.对于一个对象来说,它的属性方法(私有的/公有的)存在“枚举”的特点:在FOR IN循环的时候是否可以遍历到,能遍历到的是可枚举的,不能遍历到的是不可枚举的【内置类原型上自己扩展的方法是可枚举的】

之前例题
String.prototype.queryURLParams = function queryURLParams(key) {
// this -> 当前要处理解析的URL
let obj = {};
this.replace(/([^?&=#]+)=([^?&=#]+)/g, (_, $1, $2) => obj[$1] = $2);
this.replace(/#([^?&=#]+)/g, (_, $1) => obj['_HASH'] = $1);
return typeof key === "undefined" ? obj : obj[key];
};
let url = "http://www.zhufengpeixun.cn/?lx=1&from=wx#video";
let result = url.queryURLParams();
console.log(result);
String.prototype.indexOf = function indexOf() {
return 'OK';
};
console.log(url.indexOf('?'));
(function () {
function handleNum(num) {
num = Number(num);
return isNaN(num) ? 0 : num;
}
Number.prototype.plus = function plus(num) {
num = handleNum(num);
return this + num;
};
Number.prototype.minus = function minus(num) {
num = handleNum(num);
return this - num;
};
})();
let n = 10;
let m = n.plus(10).minus(5);
console.log(m); //=>15(10+10-5)
// obj.__proto__=Object.prototype;
// AAA是可枚举的属性了
Object.prototype.AAA = function AAA() {};
let obj = {
name: 'zhufeng',
age: 11
};
for (let key in obj) {
// 在遍历的时候,对于原型上扩展的公共属性方法,我们过滤掉,只遍历对象中私有的属性方法(必须是可枚举的)
if (!obj.hasOwnProperty(key)) break;
console.log(key);
}