js数据类型、内置对象、类型判断、隐原型__proto__、原型对象prototype

6种基本数据类型、2种引用类型:
Number,String,B
oolean,Null,Undefined,Symbol;Array、Object
用typeof可以检测出变量的基本数据类型,但是有个特例,就是null的typeof返回的是object,这个是javascript的历史Bug;ES6新增数据类型Symbol: 表示独一无二的值;
栈:原始数据类型(Undefined,Null,Boolean,Number、String) 
堆:引用数据类型(对象、数组和函数)
内置对象:
  • Object
  • Number
  • String
  • Boolean
  • Array
  • Function
  • Date
  • RegExp
  • Error
  • EvalError:代表了一个关于 eval 函数的错误.
  • RangeError:值超出范围
  • ReferenceError:引用了一个不存在的变量。
  • SyntaxError:当JavaScript引擎在解析代码时遇到不符合语言语法的令牌或令牌顺序时,会抛出SyntaxError。
  • TypeError:表示值的类型非预期类型
  • URIError:全局URI句柄函数使用错误。
var a = 'guojing'
console.log(typeof a)
输出:string

var b = 311
console.log(typeof b)
输出:number

var c = true
console.log(typeof c)
输出:boolean

var d = []
console.log(typeof d)
输出:object

var e = {}
console.log(typeof e)
输出:object

var f = null 
console.log(typeof f)
输出:object

console.log(typeof g)
输出:undefined

var h = function(){}
console.log(typeof h)
输出:function

1.在JS里,万物皆对象。方法(Function)是对象,方法的原型(Function.prototype)是对象。因此,它们都会具有对象共有的特点。即:对象具有属性proto,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。

2.方法(Function)方法这个特殊的对象,除了和其他对象一样有上述proto属性之外,还有自己特有的属性——原型属性(prototype),这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。

L instanceof R 
//instanceof运算时,通过判断L的原型链上是否存在R.prototype
L.__proto__.__proto__ ..... === R.prototype ?
//如果存在返回true 否则返回false
constructor 就是返回对象相对应的构造函数
console.log([].constructor == Array);  //true
console.log({}.constructor == Object);  //true
console.log("string".constructor == String); //true
console.log((123).constructor == Number);  //true
console.log(true.constructor == Boolean);  //true
注意:
使用instaceof和construcor,被判断的array必须是在当前页面声明的!比如,一个页面(父页面)有一个框架,
框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量,
这时判断该变量,Array == object.constructor;会返回false;
原因:
1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。
2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array。
使用
    Object.prototype.toString.call(arr) === '[object Array]'
判断 arr 是否是对象或者数组

function isArray(o) {
  return Object.prototype.toString.call(o);
}
var arr=[2,5,6,8];
var obj={name:'zhangsan',age:25};
var fn = function () {}
console.log(isArray(arr)); //[object Array]
console.log(isArray(obj)); //[object Object]
console.log(isArray(fn));  //[object function]
1.一个对象的 __proto__隐式原型 指向构造该对象的构造函数的 prototype原型对象;

2.实例能够访问在构造函数 原型对象prototype 中定义的属性和方法;
3.函数是个特殊的对象,除了和其他对象一样有 隐式原型proto之外,还有自己特有的 原型对象prototype;
4.原型对象prototype 的用途就是包含所有实例共享的属性和方法。

5.原型对象
prototype 也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。
6.在js里,万物皆对象;
var A = function(){}
var a = new A()
console.log(a.__proto__);
console.log(A.prototype);
输出:{constructor: ƒ}constructor: ƒ ()__proto__: Object
console.log(a.__proto__.__proto__);
console.log(A.prototype.__proto__); console.log(Object.prototype); 输出:{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}constructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()arguments: (...)caller: (...)length: 1name: "set __proto__"__proto__: ƒ ()[[Scopes]]: Scopes[0]
console.log(a.__proto__.__proto__.__proto__);
console.log(A.prototype.__proto__.__proto__); console.log(Object.prototype.__proto__); 输出:null

通过现代浏览器的操作属性的便利性,可以改变一个对象的 [[Prototype]] 属性, 这种行为在每一个JavaScript引擎和浏览器中都是一个非常慢且影响性能的操作,使用这种方式来改变和继承属性是对性能影响非常严重的,并且性能消耗的时间也不是简单的花费在 obj.__proto__ = ... 语句上, 它还会影响到所有继承来自该 [[Prototype]] 的对象。

如果你关心性能,你就不应该在一个对象中修改它的 [[Prototype]].。相反, 创建一个新的且可以继承 [[Prototype]] 的对象,推荐使用 Object.create()

Object.prototype.__proto__ 已被大多数浏览器厂商所支持的今天,其存在和确切行为仅在ECMAScript 2015规范中被标准化为传统功能,以确保Web浏览器的兼容性。为了更好的支持,建议只使用 Object.getPrototypeOf()

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

const person = {
    isHuman: false,
    printIntroduction: function () {
        console.log(`My name is ${this.name}. Am I human?${this.isHuman}`);
    }
};

const me = Object.create(person);

me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // 继承的属性可以被覆盖重写

me.printIntroduction();  //expected output: "My name is Matthew. Am I human? true"
Object.getPrototypeOf() 方法返回指定对象的原型
const prototype1
= {}; const object1 = Object.create(prototype1); console.log(Object.getPrototypeOf(object1) === prototype1);
输出:true
console.log(obj1.__proto__ === prototype1);
输出:true
再次理解三种实例化对象的方式:
var
a={} console.log(a.__proto__) 输出:{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}constructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()
var B = function(){} var b = new B() console.log(b.__proto__) 输出:{constructor: ƒ}
var c = Object.create(a) console.log(c.__proto__) 输出:{}
var d = Object.create(b) console.log(d.__proto__) 输出:B {}
工欲善其事 必先利其器
原文地址:https://www.cnblogs.com/fengyouqi/p/9567264.html