几个小例子让你明白原型、继承、作用域
今天整理电脑,发现了很多早些年初学js时,一些比较困惑的程序题。然后摘抄出了其中的一些,有关原型、继承、作用域等相关的。供初学者学习,其中若有我理解错误的,欢迎大家批评指正。
下面不多说废话,直接上内容。
1、对象中属性或方法先从事例中寻找,若没有才去原型中寻找。
function A () {} function B(a) { this.a = a; } function C(a) { if (a) { this.a = a; } } A.prototype.a = 1 B.prototype.a = 1; C.prototype.a = 1; console.log(new A().a); // 1 console.log(new B().a); // undefined console.log(new C(2).a); // 2
2、原型链继承演示(简版)
function Fn() { console.log(1); } var fn = new Fn(); console.log(fn); // FN console.log(fn.__proto__ == Fn.prototype); // true console.log(Fn.__proto__ == Function.prototype); // true console.log(Function.prototype.__proto__ == Object.prototype); // true console.log(Object.prototype.__proto__); // null
3、ES6继承
class Animal { constructor(){ this.type = 'animal' } says(say){ console.log(this.type + ' says ' + say) } } let animal = new Animal() animal.says('hello') // animal says hello console.log(animal.constructor); // FUN Animal class Cat extends Animal { constructor(){ super(); //修改this指向 this.type = 'cat' } } let mini = new Cat(); console.log(mini.constructor == Cat); // true 实例的constructor指向构造函数 console.log(mini.type); // cat console.log(mini.__proto__ == Cat.prototype); // true console.log(Cat.prototype.__proto__ == Animal.prototype); // true console.log(Animal.prototype.__proto__ == Object.prototype);// true console.log(Object.prototype.__proto__); // true
4、作用域
1. 最近的作用域声明过,则去就近取 var tt = "a"; function test(){ //函数内部作用域声明过,所以会就近取。var 有声明提升。 //相当于在本作用域前声明 console.log(tt); // undefined var tt = "b" console.log(tt); // b } test(); function test2(){ //函数内部作用域没有声明过, //直接从外部取值,调用。 console.log(tt); // a } test2(); 2. 作用域发生变化 var length = "aaa" //若注释这句, window的length就为0 function fn(){ console.log(this.length); } var obj = { length:"bbb", test:function(fn){ fn(); // aaa this 为 window console.log(this.length); ·// bbb this 为 obj arguments[0](); // 1 this 为 arguments 对象 arguments的length为1 } } obj.test(fn);
3. this 指向 function fn(a,b){ alert(this+","+a); } fn.call("web",4,10) // web,4 var _name = "window name"; var hero = { _name:"John Doe", getName:function(){ return this._name; } } var st=hero.getName; console.log(st()); // window name 此处this为window console.log(hero.getName()) // John Doe 此处this为hero对象 4. 原型,继承 function SuperType(){ this.car="宝马"; this.home="大别墅"; } function SubType(){ } SubType.prototype=new SuperType() var pp=new SubType() console.log(pp.car) // 宝马 5. 函数别名作用域 var func = function a (){ console.log(typeof a); // function } func(); console.log(typeof a) // undefined // 在函数内部可以找到a, // 但在外部a不存在,只有func; 6. 函数内修改值 var a = 1; var obj = {b:2}; var fn = function(){}; fn.c = 3; function test(x,y,z){ x = 4; y.b = 5; z.c = 6; return z } test(a,obj,fn); console.log(a+obj.b+fn.c); // 12 1, 5, 6 // 在函数内部,若直接修改参数的值,该值不会传递在外部, // 但修改参数内部的某属性时,则可以改变 7. 作用域优先级问题 var a = 1; function fn(a){ console.log(a); var a = 3; function a (){}; } fn(2); // function // 函数作用域同名变量,函数优先打印出来,其次是参数,再然后是局部变量,最后是全局变量。 // 那么意味着,暂且抛开全局变量不谈,局部变量 var 先声明提升,再然后是参数,最后是函数。 // 所以在程序开始运行的时候只能找到函数的值。 // 可能语言描述不清,看例子即可。 // 若注释 function a (){}; 打印值为 2 var a = 1; function fn(a){ console.log(a); var a = 3; } fn(2); // 2 // 若再去掉参数 打印值为 undefined 声明提升。 var a = 1; function fn(){ console.log(a); var a = 3; } fn(); // 若再去掉var a = 3; 打印值为 1 var a = 1; function fn(){ console.log(a); } fn(); // 整体声明提升遵循这样一个规律, 局部变量 var > 参数 > 函数
好了,今天就暂时分享到这里。